home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1994 #1
/
monster.zip
/
monster
/
OS2
/
WOR_11.ZIP
/
GI
/
GI.INF
(
.txt
)
next >
Wrap
OS/2 Help File
|
1993-12-13
|
27KB
|
721 lines
ΓòÉΓòÉΓòÉ 1. Abstract ΓòÉΓòÉΓòÉ
Abstract
GI is a generic Interface between Games and Input Devices.
GI was designed to detach the task of getting and normalizing data from input
devices from the task of programming a game.
The following picture may clarify this:
GAMES INPUT DEVICES
ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
Γöé Wizard of Wor Γöé<ΓöÇΓöÉ ΓöîΓöÇ<ΓöÇΓöé Keyboard Γöé
ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ Γöé Γöé ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ Γöé ΓòöΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòù Γöé ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
Γöé Boulder Dash Γöé<ΓöÇΓö╝ΓöÇΓöÇ<ΓöÇΓöÇΓöÇΓòæ GI Γòæ<ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇ<ΓöÇΓöé Joystick Γöé
ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ Γöé ΓòÜΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓò¥ Γöé ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ Γöé Γöé ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
Γöé Tron Γöé<ΓöÇΓöñ Γö£ΓöÇ<ΓöÇΓöé Straight Γöé
ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ Γöé Γöé ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
Γöé Γöé
... ...
Therefore:
o An Input Device knows how to handle data from a device (eg. a Joystick or a
keyboard).
o A Game does not care what kind of Input Device the user prefers. It just
queries GI for user input.
Or with other words:
GI is a black box that hides all information about the user preferences of
input devices from the game.
ΓòÉΓòÉΓòÉ 2. Highlights ΓòÉΓòÉΓòÉ
Special Highlights of GI version 1.0
o Interface for Games and Input Devices fully written in C
o Source code is available
o Sample code for both Games and Input Devices available
o GI is configured once for all Games!
o Possibility for per-Game configuration exists
o Analog Input Devices can be used with Games requireing digital user input and
vice versa (although this has not been tested yet...)
o Up to 10 Players can play simultaneously!
ΓòÉΓòÉΓòÉ 3. Installation ΓòÉΓòÉΓòÉ
Installation
GI consists of two ZIP-Files:
o GIRUN.ZIP (all files needed to run GI)
o GISRC.ZIP (all source files for GI)
These two ZIP-Files are bound together in GI.ZIP (as you noticed...). If you
just want to use GI, you just unzip GIRUN.ZIP. It contains all modules
required.
The GISRC.ZIP file contains all the source code of GI! You don't need to unzip
the TOOLS.ZIP, PMTOOLS.ZIP and STD.ZIP files if you don't recompile GI.
Installation step by step
1. Create a directory named "GI". GI is used in more than one game, so this
step makes sense even if you don't like it...
2. Copy GIRUN.ZIP to this directory and change (cd) to it.
3. Unzip GIRUN.ZIP.
4. Make sure the following files have been unzipped correctly:
o GI.DLL
o GICONFIG.EXE
5. Edit your CONFIG.SYS file:
a. Append the full drive and path name of the GI-directory to your
LIBPATH-entry:
LIBPATH=...;C:\GI
Otherwise you'll have to put all the dynamic link libraries (*.DLL) of
GI to a location already mentioned in your LIBPATH-entry.
b. Add the following line to the end of your CONFIG.SYS:
SET GICONFIG=C:\GI\GICONFIG.DAT
(Assuming you installed GI in a directory "GI" on the C: drive.)
c. If you have a PC-Joystick, add the following line to your CONFIG.SYS:
DEVICE=C:\GI\GAMEPORT.SYS
(Again assuming you installed GI in C:\GI.)
6. Restart your system for the changes in CONFIG.SYS to take effect...
That's it. After the restart of your system you can continue by configuring GI.
ΓòÉΓòÉΓòÉ 4. Configuration ΓòÉΓòÉΓòÉ
Configuration
GI knows two diffrent kinds of configurations:
1. Global/Default configuration
2. Local configuration
Basics
One of the base ideas behind GI was, that one configuration should be enough
for all kind of games. To statisfy this criterion GI has a global configuration
file (GICONFIG.DAT) that holds all information for the input devices. This file
is located as mentioned in the installation section.
But since the restriction to only one configuration may be too hard (imagine a
game that uses really weird controls) the possibility for a local configuration
was introduced. This local or per-game configuration works just the same way as
the global configuration does. The only difference being that the configuration
file for the local configuration is located in the directory of the game
whereas the global configuration file resides in the GI directory.
Configuration of GI
Configuration of GI and its input devices is done with the GICONFIG program.
This program uses a standard OS/2 Presentation Manager interface. Configuration
is performed in two steps:
1. Select an input device from the list or define a new by pressing the New
Player button and selecting one from the list presented. (You'll have to
select the proper directory first, of course...)
Note: Currently available devices are:STRAIGHT.DLL, KBD.DLL, JOY.DLL and
TAPEDEV.DLL. See Devices for further information.
2. Start the configure part of the selected device by pressing the Define
button or double-clicking in the list of devices.
Note: Device 1 will be queryed for input to move player 1, device 2 for player
2, etc.!
Special Hint when inserting new devices
When you hit the New Player button and no device in the list is highlighted,
the new device will be inserted at the end of the list. If there is already a
device highlighted, the new one will be inserted before the highlighted device!
ΓòÉΓòÉΓòÉ 5. Devices ΓòÉΓòÉΓòÉ
Devices
GI cannot work without input devices (see Abstract). The most important devices
have already been realized and are part of this version of GI.
Since GI is meant to be a generic interface, everybody is encouraged to
implement further devices. Detailed info in Writting a new Device.
Prepared, but not implemented yet, is the possiblity to implement "intelligent"
computer players. Such a computer player device would of course need further
information about the rules and strucutres of a game. But for the game (and the
game programer) the computer player would be fully transparent. The game would
not be able to distinguish a human player from a computer player. This concept
hat already been used in realizing the Tape Recorder device.
ΓòÉΓòÉΓòÉ 5.1. Interface from GI to Devices ΓòÉΓòÉΓòÉ
Interface from GI to Devices
Note: This section is for programers only.
Every device is placed in a dynamic link library that gets loaded and called by
GI. Therefore all devices have the same interface to GI and use excatly the
same mechanism for excanging data.
A device must suffice to the following requirements:
o Must contain the functions _GetDataSize, _InitializeDLL, _Name, _ConfigDLL,
_Threshold and _Direction with the parameters as specified below
o Must be callable with std. C-calling conventions
The reason for these requirements being that GI comunicates with the device
only through these functions. Furtheron, the adresses of these functions are
calculated using a call-by-name mechanism (that's why the names are very
important).
Required functions in a device
o _GetDataSize (void): Returns the number of bytes required to hold all data,
that the device needs to run (see instance data below).
o _InitializeDLL (char __far16 *id): When GI is initialized, the devices are
initialized with this function. They receive a pointer to a piece of memory
(id) as parameter. The piece of memory has the size returned by the
_GetDataSize() function of the device. I recommend to have a flag initialized
in the instance data to detect, if the data area has already been initialized
with default values or not.
o _Name (char __far16 *mm): Copies the name of the device in ascii
representation to the memory location (mm) specified by the parameter. This
name is shown in the device-list in GICONFIG.
o _ConfigDLL (char __far16 *id): Every device should have a configuration part.
GI calls this part, when the user selects a device and presses the Define...
button. The configuration should have a Presentation Manager interface (like
the included devices have). In the configuration part, the user may do all
that is needed to use the device for playing afterwards (definitions,
calibrations of the device, ...).
Note: The selections and definitions that should be saved, must be placed in
the instance data. GI will save this area for you!
o _Threshold (char __far16 *id): This function is called to convert analog to
digital values.
Example 1:
analog Joystick: device returns value=0..100
GI: if game wants analog values then
return value
else
if value < threshold then
return 0
else
return 1
Example 2:
(digital) Keyboard: device returns value=0 or threshold
GI: return value to game
As you notice, the threshold value has a different meaning for analog and
digital devices.
Note: All devices return values in the range 0..100. Digital devices must
return the threshold value instead of 1.
o _Direction (char __far16 *id, char __far16 *pi): This function is called
whenever the game wants the actual values from the device. Parameters are:
- id: Pointer to the instance data.
- pi: Pointer to the PLAYERINFO-structure given to GI by the game. The
device fills the direction[] field of this structure. GI calculates the
direction, diagonal and buttons fields afterwards from the values found in
the direction[] array.
Note: The leading underscore (_) is appended automatically, if you program in
C or declare the functions extern "C" in C++.
Instance data
The same device may be configured for more than one player (eg. two players
playing on the same keyboard). GI creates a new instance for every configured
use of the device (eg. different keys to move the figures). Therefore all
configured data should be placed in the instance data. GI will keep track of
saving and reloading the instance data for the devices. Don't create any
configuration files and don't use the Profile-functions of Presentation Manager
since you cannot be sure that your device will run with PM present! Furtheron
you should avoid using global variables even if you define your device to have
single nonshared data areas. The reason being that your device may be loaded
more than once within the same process and hence sees the same global data in
all instances.
Writting a new Device
ΓòÉΓòÉΓòÉ 5.2. Writting a new Device ΓòÉΓòÉΓòÉ
Writting a new Device
It's easy!
Note: This section is for programers only.
I suggest you copy one of the existing devices (as close as possible to the one
you want to implement) and modify it. Some modifications are needed if you
don't use Borland C++. But in principle, it's very easy:
o Make sure you #include <gi.h>
o Define all functions as desrcibed in Interface from GI to device
o Implement a minimul functionality and compile your module to a DLL.
o Verify the correctness of the names with a library manager (if GI cannot find
all functions, it will refuse to load the devie).
o Try loading your device in GICONFIG
o Implement the full functionality of your device
o Send your device to me for distribution in the next release! This step is
optional but strongly recomended!
Note: If you need to debug your device, you'll need to recompile all parts of
GI. To do this you need the sources in TOOLS.ZIP also contained in this
distribution. You may use the GIMAKE.CMD command file if you work with Borland
C++.
ΓòÉΓòÉΓòÉ 5.3. Supported Devices ΓòÉΓòÉΓòÉ
Supported Devices
Distributed with GI are some input devices. The source code for these is also
contained in the GISRC.ZIP file.
Planned are devices for:
o Game-Demos (Intros, etc.)
o Computer-Player
o Mouse (?)
Refinement and enrichment of existing devices is also possible...
ΓòÉΓòÉΓòÉ 5.3.1. Straight Auto-Player ΓòÉΓòÉΓòÉ
Straight Auto-Player
This device was designed to make debugging of games easier. It provides the
possibility of an player walking always in the same direction (or standing
still).
This device is also very usefull to fill the list of installed players...
ΓòÉΓòÉΓòÉ 5.3.2. Joystick ΓòÉΓòÉΓòÉ
Joystick
There are two kinds of joystick available on the market:
o Digital Joysticks and
o Analog Joysticks
The difference is very simple: Digital joysticks have (mostly) a mechanical
switch for every of the 4 directions (North, East, South and West) and the
fire-buttons. Analog joysticks have (mostly again) 2 variable resistors which
are connected to the stick in a manner, that their resitance changes as the
stick is moved in x- or y-direction. The actual value of these resistors gets
sampled (10 times per second) and digitized by the game-port. To access the
game-port under OS/2 the GAMEPORT.SYS driver must be installed.
Note: Support for digital joystick is not yet implemented.
Configuring the analog Joystick
The values of the resistors in a joystick vary from product to product. To
calculate the exact values and scale of the joystick, the resitor values at the
extremal points (upper left and lower right corner) must be taken. This is
called calibration.
The calibration part of the joystick input device configuration can be
activated by pressing the Define Max.-button in the joystick configuration.
The joystick configuration dialog shows on the left side the analog behaviour
of the joystick. If you move the stick, the tiny black point (should) change
its position...
Note: If the tiny point does not follow the movements of your joystick,
JOYSTICK.SYS may not be installed. Check Installation
On the right side of the configuration dialog you see the digital
representation of the analog values on the left. Depending on the selected
threshold the checkboxes check with more or less movement of the stick. We
recomend to experiment with the setting for the threshold because this is
crucial for the behaviour in games requireing digital input!
ΓòÉΓòÉΓòÉ 5.3.3. Keyboard ΓòÉΓòÉΓòÉ
Keyboard
The Keyboard Device works both in OS/2 Presentation Manager and OS/2 Full-
Screen mode (ever tried to do this?). It intercepts all keyboard activities and
checks wheter the actually pressed key (or combination of keys) matches any
defined pattern.
Configuration
1. Select the direction or button you want to define the key(combination) for.
2. Press the DEFINE button
3. Press the START button in the new dialog window
4. Hit the key(combination). The scan-values and state of the control-keys are
displayed.
5. If you hit the correct key(combination) press the STOP button
6. Hit the TEST button and afterwards press your key(combination). If you hear
a short beep, your key(combination) was accepted.
7. Hit the OK button, your definition is completed.
8. Go back to point 1 if you want to define more directions or buttons.
Note: An asterisk * on the left of a direction or key signals that it has been
defined.
Warning: Define diferent keys for button 1 and button 2 since some games may
distinguish between the buttons!
Threshold
The Threshold slider comes to action, when the keyboard is used in a game
requesting analog input. Since it is impossible to tell how strong a key is
typed, the treshold value is used instead of 0 (key not pressed) and 1 (key
pressed)...
Note: The Keyboard device is also used XFEEL and BUILDER.
ΓòÉΓòÉΓòÉ 5.3.4. Tape Recorder ΓòÉΓòÉΓòÉ
Tape Recorder
The Tape Recorder consists of two parts:
o TAPEDEV.DLL: input device for GI
o TAPE.EXE: Program to control the tape
The idea of the tape recorder is, that you can monitor and record input from
any other device and play it back later. The concept may be known from
keyboard-monitors that let you define and play back a series of keystrokes. The
Tape Recorder works just this way: You start recording and play the game. All
your movements get recorded. Later on you can play this session back.
Stop on Overplay option
This feature lets you interrupt (better stop) the playing back of a recorded
tape. Just let the tape run until you feel to take over. As soon as you move
your device you will override the tape and stop its running.
Note: This feature can be turned on and off in the Tape Recorder program.
Configuring the Tape Recorder
1. Install a Tape Recorder Device (TAPEDEV.DLL) for the player you want to
record
2. Configure the Tape Recorder device: The port number must match the device
you want to move your figure with.
3. Finish configuring GI
Say: You want to monitor player 1 in a game. Input comes from keyboard.
Then: You define the tape device a device number 1. The keyboard must also
be defined (eg. number 3). Then you configure the tape devie to monitor
port number 3. OK?
Recording
1. Start the Tape Recorder program (TAPE.EXE)
2. Select a file with the File...-button or enter a filename for the tape.
3. Start your game and make selections and other stuff you don't want to be
recorded.
4. Switch back to the Tape Recorder and press the RECORD button.
5. Switch to the game again and play. The Tape Recorder is now recording!
6. As soon as you like, switch back to the Tape Recorder and press the STOP
button. Your tape is ready!
Playing back
1. Start the Tape Recorder program (TAPE.EXE), but only if it's not running...
2. Select the file to play back.
3. Start your game and move to the point your recording started.
4. Switch back to the Tape Recorder and press the PLAY button. Your tape is
running!
5. If the "Stop on Overplay" option is checked, you can stop the show with a
single movement from your original device!
Note: Play back will stop as soon as the end of the tape is reached.
Concept of the Tape Recorder
Let's look at it from the point of view of a game.
The game wants user input. It calls GI with the number of the player. GI looks
at its internal table, which device corresponds to the requested player. Then,
GI requests the actual data from the device, normalizes it and returns it to
the game.
Now the Tape Recorder consists of a Tape Device which can be called from GI as
any other device. But the Tape Device does not query any hardware. Instead it
calls GI and queries the actual data for the player configured. In Record-mode
the data is stored in a file and in Play-back-mode data is loaded from disk
instead of querying GI for the original device.
ΓòÉΓòÉΓòÉ 6. Games ΓòÉΓòÉΓòÉ
Games
All started with Wizard of Wor. At a certain point in the process of developing
the game, we had to decide how to get the user input to move the figures. Since
we didn't have a joystick or any other input device than mouse and keyboard
we "hard coded" the input-part of the game.
But of course we were not content with this kind of restriction. And after we
released the game to public several people asked for joystick support. Now it
would have been easy to simply add this part, but as we were already planing
our next game (Boulder Dash), a generic solution to this problem seemed more
convenient...
Since GI cannot exist without GAMES, we want to encourage everybody to adapt
existing games or write new games using GI for the user input!
ΓòÉΓòÉΓòÉ 6.1. Interface from Game to GI ΓòÉΓòÉΓòÉ
Interface from Game to GI
Note: This section is for programers only.
Requirements
The game must be programmed in a language that allows C-functions to be called.
Therefore the library GI.LIB must be linked to the game that uses GI.
There are no problems if the game is written in C or C++, allmost any compiler
should be OK...
Note: GI.LIB contains just the definitions for the linker to know, that GI.DLL
must be loaded to actually execute the GI-functions.
Interface functions and data structures
There are only two functions and one data structure required for using GI in a
game:
o PLAYERINFO-structure
o GIInitialize()
o GIGetDirection (PLAYERINFO *)
The prototypings and definitions are in GI.H which must be included to import
the functionality of GI.
Meanings of data-members in PLAYERINFO-structure
typedef struct _playerinfo
{
// Input Data
unsigned player; // Number of actual player
BOOL analog; // Game wants analog-values
int x; // Actual position x (optional)
int y; // Actual position y (optional)
// Output Data
char dir[6]; // Values of directions: Up, Right, Down, Left, B1, B2
char direction; // Strongest direction or DIRNONE
char diagonal; // 2nd strongest direction or DIRNONE
char buttons; // 2 bits for buttons
// Strategy Data
unsigned (*Move) (unsigned x, unsigned y); // Callback to Game!
void *stratdata; // Data for Strategy-Instance
} PLAYERINFO, *PLAYERINFOP;
player: Zero-based number of player for which you want the actual direction and
button values.
analog: TRUE if game wants analog values in the range of 0..100 for each of the
four directions (see below). FALSE if game wants digital input (eg. player
moves up, strenght not required).
dir[6]: Actual values of the queried device of the 4 directions and the 2
buttons.
direction: Strongest/main direction coded as mentioned below.
diagonal: Second strongest/secondary direction. If you don't care about
diagonal moves, just ignore this field. Otherwise the actual direction is
between direction and diagonal (direction=up, diagonal=left --> diagonal left
up).
buttons: Binary representation of the states of the two buttons. If a button is
pressed the corresponding bit is 1.
Note: All other fields in PLAYERINFO are not used yet!
Coding of the directions
#define DIRNONE -1
#define DIRUP 0
#define DIRRIGHT 1
#define DIRDOWN 2
#define DIRLEFT 3
#define DIRBUT1 1
#define DIRBUT2 2
The definitions of the four directions are as well the indices into the
direction[] array as the values of the direction and diagonal fields in
PLAYERINFO.
Consider the following example:
/* pi.player and pi.analog must be initialized ! */
if (GIGetDirection (&pi))
{
/* A error occured, see errdef.h for further coments...
}
if (pi.buttons)
{
/* process buttons now.... */
}
if (pi.direction != DIRNONE) /* or use: pi.dir[] .... */
{
/* process direction .... */
}
Warning: Don't forget to call GIInitialize() somwhere in the startup of your
game!
Comments
o Typically, you allocate a PLAYERINFO-structure for every player your game
will support.
o The fields for strategy functionality are not yet used, since I don't have a
good concept for an example of such a strategy player yet...
o The interface was designed to be as narrow as possible to make it easier to
use.
ΓòÉΓòÉΓòÉ 6.2. Games supporting GI ΓòÉΓòÉΓòÉ
Games supporting GI
The three games that we wrote up to now have two things in common:
1. They use GI for getting user input
2. Two players can play at the same time
We don't want to make the impression of being "Game-Freaks", but we like
playing games and even more than that, we like to write programs. Not
necessarly games, well noted. Games are the ideal trade off between writting
good software and having some fun afterwards...
And by the way: We also wanted to show that OS/2 is a good operating system!
ΓòÉΓòÉΓòÉ 6.2.1. Wizard of Wor ΓòÉΓòÉΓòÉ
Wizard of Wor
Wizard of Wor is a port from an old C64 game. It was always one of my
favourite: simple but fascinating...
The OS/2-port was done in C++, all code rewritten. The pictures and dungeons
are the same as in the original (took us quite some time to capture all the
figures...). Some differences occur in the speed-up during the game and the
speed of Worluk and the Wizard.
Wizard of Wor is a real CPU-hog. One big problem was, that the maximal timer
resolution of OS/2 (32ms) was far too slow. So we decided to do a busy-waiting.
The mechanism of slowing the game down in a way that fast maschines are slowed
more than slow maschines was invented by Markus and is unique (well sort
of...).
Note: Our highscore on the original C64 Wizard of Wor is at 194'800 points in
two player mode!
ΓòÉΓòÉΓòÉ 6.2.2. Boulder Dash ΓòÉΓòÉΓòÉ
Boulder Dash
An all time goodie. It exists on almost every game computer. This can be seen
as a port of the AMIGA version of Boulder Dash. Most of the ideas for the
special objects such as bombs, enemies, swamp, ..., were taken from there.
For those how don't know Boulder Dash
You (and perhaps your friend) are lost in a system of underground caves. Your
task is to collect the diamonds and enter in the house. You can not proceed to
the next level until you completed the level...
ΓòÉΓòÉΓòÉ 6.2.3. Tron ΓòÉΓòÉΓòÉ
Tron
Famous motion picture. A real must for all computer freaks. First movie with
computer animated sequences (as far as I know).
The game was introduced in the film. Two players, both try to lock each other
without crashing into the walls. This game is anything but perfect, many bugs
still wait to be fixed...
ΓòÉΓòÉΓòÉ 7. About 'n Credits ΓòÉΓòÉΓòÉ
About 'n Credits
GI is free! Please use, extend, spread, ... GI as you like.
For further enhancments, comments, questions or bugs please send an email or a
short note:
Roman Fischer
Leonhardstr. 12
CH-8001 Zuerich
Switzerland
rofische@iiic.ethz.ch
Credits
Special thanks go to Markus Hof, who always helps me out of conceptual troubles
and ported Wizard of Wor to GI!
Credits to: Andre "Infid" Miodonski, ...
Thanks to ICA Systems Inc. for their joystick driver, which is included in the
standard version of GI.