SHOGO Joystick Configuration Made Easy (almost)

Overview

With the release of version 2.2, Shogo supports extended joystick features such as analog movement and multiple-axis control. Shogo supports these extended joystick features via a new separate JOYSTICK.CFG file.

How it works

If a JOYSTICK.CFG file is present in the main Shogo directory (usually c:\games\shogo) when the game is launched, Shogo will read-in the settings from the JOYSTICK.CFG file and then use them in the game.

Note that the JOYSTICK.CFG file will override any settings that you've made through the in-game Joystick menu, and that the in-game Joystick menu will also be disabled. Removing the JOYSTICK.CFG file from the main Shogo directory will re-enable the in-game Joystick menu.

Making it work

To use one of these pre-made sample .cfg files, save the sample .cfg file as JOYSTICK.CFG into your main Shogo install directory (usually c:\games\shogo). If the JOYSTICK.CFG file exists in your c:\games\shogo directory when Shogo is launched, the JOYSTICK.CFG file will be used by the game.

Sample .cfg files

There are several sample joystick configuration files included in the \joystick directory for your reference. Each .cfg file contains a short header section that describes its basic functionality (these descriptions are also listed below). You can view or edit the sample .cfg files by using a text editor (such as Notepad).

JOY1.CFG | Standard Analog Joystick Forward/Backward Movement Left/Right Strafe
JOY2.CFG | Standard Analog Joystick Forward/Backward Movement Left/Right Turn
JOY3.CFG | Standard Analog Joystick Look Up/Down and Left/Right Turn
JOY4.CFG | Standard Digital Joystick Forward/Backward Movement Left/Right Strafe
JOYPXL.CFG | Panther XL Standard Setup--trackball for Left/Right and Up/Down and joystick for Forward/Backward and Left/Right Strafe
JOYPXL2.CFG | Panther XL Standard Setup 2-- trackball for Left/Right and Up/Down and joystick for Forward/Backward and Left/Right Strafe, different button setup than joypxl.cfg
JOYS360.CFG | SpaceOrb 360 Analog Bindings
JOYS360D.CFG | SpaceOrb 360 Digital Bindings
JOYURG1.CFG | UR Gear Headset+Joystick Standard Setup

WE STRONGLY RECOMMEND THAT YOU TRY A SAMPLE .CFG BEFORE EDITING ANY .CFG FILES. The sample .cfg's support a variety of joysticks, and it's likely that one will work well for your joystick. However, we realize that there are still some people who like anchovies on their pizza, so if none of the sample files work for you, keep reading—there's plenty of info on how to customize the .cfg's.

PantherXL support

There are 2 .cfg files that were designed specifically for the MadCatz PantherXL. You may need to tweak the hat/button/weapon bindings, but one of these should work well for you if you're a Panther owner.

Hey! Where's the .cfg for my UltraVibe Pleasure 2000?

We've listed a few .cfg's for several generic joysticks, as well as some specific models. However, there are many, many joysticks that aren't listed here. Some joystick manufacturers provide game-specific configuration files for their products, so we suggest checking with your joystick manufacturer (or the Shogo website www.shogo-mad.com) to see if they have a .cfg for Shogo.

DirectInput

DirectInput is part of Microsoft's DirectX technology, and it's the way that Shogo talks to different types of input devices like mice, gamepads, keyboards and joysticks. You will see DirectInput mentioned occasionally in this document when we're talking about communication with joysticks.

Tweaking or writing your own JOYSTICK.CFG

The best way to create your own .cfg is to start with one of the sample .cfg's and then edit it. Getting a .cfg file "just right" will take some tweaking on your part, but once you get it, you'll have it forever.

The command syntax and value ranges are explained in detail in this document, so if you run into trouble, you should be able to find the answers here.

WARNING: Although the .cfg files appear simple at first glance, they're actually pretty complicated. Reading over this document will give you a better understanding of how they work. Reading over this document will also ensure that you will never, ever make the mistake of trying to write input code for a fps (or any other game, for that matter).

File header

Every JOYSTICK.CFG must include the following text at the top of the file:

-joystickdescription "Joystick Configuration Description"

-joystickmenudisabled 1

enabledevice "Joystick 1"

AddAction AxisYaw -10001
AddAction AxisPitch -10002
AddAction AxisLeftRight -10003
AddAction AxisForwardBackward -10004

-joystickdescription "Joystick Configuration Description"

The text inside the " " can be replaced with any description you choose for this .cfg file.

-joystickmenudisabled 1

This disables the in-game joystick menu. If this line is removed, strange things will happen when you try to edit the joystick configuration through the in-game menus.

enabledevice "<device name>"

The enabledevice "<devicename>" command tells Shogo to activate the a specified input device. You may add multiple enabledevice commands if you are using multiple joysticks (eg, you may have 2 joysticks installed, "Joystick 1" and "Joystick 2").

AddAction <action-name>

The AddAction <action-name> command tells Shogo to add a game event to the list of possible events. Note that every game event (firing, jumping, moving forward, next weapon, previous weapon, etc.) will have an AddAction associated with it.

enabledevice "Joystick 1"

This command tells Shogo to activate the "Joystick 1" device (usually the main joystick connected to your system).

AddAction AxisYaw -10001

Enables analog turn left or turn right.

AddAction AxisPitch -10002

Enables analog look up or look down.

AddAction AxisLeftRight -10003

Enables analog strafe left and strafe right.

AddAction AxisForwardBackward -10004

Enables analog move forward and move backward.

Command Types

There are three basic types of commands that are used by Shogo for joystick configurations: floating point console variables, rangebind commands, and rangescale commands.

Floating point console variables

An example of a floating point console variable:
AxisPitchDeadZone 0.00

Console variables are always formatted as:
<variable name> <numerical value>

<variable name>

Text with no spaces describing the variable name.

<numerical value>

Floating point numerical value that is assigned to the variable.

rangebind commands

An example of a rangebind command:
rangebind "Joystick 1" "##Slider 0" 0.000000 0.000000 "AxisYaw"

Rangebind commands are always formatted as:
rangebind "<device name>" "<control name>" "<low range value>" "<high range value>" "<action name>"

<device name>

Describes the DirectInput name of the device that you are using. For joysticks this is usually "Joystick 1". The <device name> must be the same as the <device name> defined in the .cfg by the enabledevice command (see the Glossary or File Header section of this document for more info on the enabledevice command).

<control name>

This is the name of an axis, button, slider, POV hat or other type of input control. A digital control (like a button) returns either an ON or an OFF state. An analog control (like the shaft of a joystick or a trackball) returns a numeric value that corresponds to the position of the control. These are described more in the section Control Names.

<low range value>

This number should always be zero if you are using an analog action or if you are using a button control. Otherwise, this value is the low range of the control value that is used to activate the digital action.

<high range value>

This number should always be zero if you are using an analog action or if you are using a button control. Otherwise, this value is the high range of the control value that is used to activate the digital action.

<action name>

This describes the name of the action (game event) that the preceding low and high range values apply to.

Special notes about the rangebind command

- The <low range value> <high range value> and <action name> values can be repeated for multiple actions using a single rangebind command.
- If the <low range value> and <high range value> are set to zero, the rangebind command will take the exact value that is returned by the control. This value will then be passed on to the specified action.
- If the <low range value> and <high range value> are not set to zero, then the value that is returned by the control is checked to see if it falls within, or is equal to, the specified range values. If the returned value does fall within, or is equal to, the specified values, then the action is set to ON.
- Multiple digital actions (eg, Fire, NextWeapon, PrevWeapon, etc.) may be used multiple times in the same rangebind command or in different rangebind commands.

rangescale commands

An example of a rangescale command:
rangescale "Joystick 1" "##Slider 0" 1.400000 -1.000000 1.000000 100.0

rangescale commands are always formatted as:
rangescale "<device name>" "<control name>" "<scale value>" "<min range scale value>" "<max range scale value>" "<pre center offset value>"

A rangescale command always follows a rangebind command. A rangescale command uses the same <device name> and <control name> as the rangebind command above it. Rangescale is an option command and should only be used if you need to scale (multiply) the numerical value that the control returns. The rangescale values take effect before the values in the rangebind command are checked. So, you must adjust the <low range value> and <high range value> in the rangebind command to take into account any scaling or offsets that you specify with rangescale.

The rangescale command first adds the <pre center offset value> to the numeric value returned by the control. Then, if the <min range scale value> and the <max range scale value> are not zero, the adjusted numeric value is scaled from its maximum and minimum possible values to fit in the specified range scale. The result is then multiplied by the <scale value> and is used by the rangebind command.

<device name>

Describes the DirectInput name of the device that you are using. For joysticks this is usually "Joystick 1". The <device name> must be the same as the <device name> defined in the rangebind command.

<control name>

This must be the same control name that is specified in the rangebind command. The <control name> is the name of an axis, button, slider, POV hat or other type of input control. A digital control (like a button) returns either an ON or an OFF state. An analog control (like the shaft of a joystick or a trackball) returns a numeric value that corresponds to the position of the control.

<scale value>

The numeric value returned by the control is multiplied by this number. If you don't want to do any scaling, this value should be set to 1.0.

<min range scale value>

This is the minimum value for use in doing a rangescale. If you do not want to scale the input to a range, then this value should be set to 0.0.

<max range scale value>

This is the maximum value for use in doing a rangescale. If you do not want to scale the input to a range, then this value should be set to 0.0.

<pre center offset value>

This offset number is added to the numeric value returned by the control before any other scaling is done. If you do not want to use an offset, this value should be set to 0.0.

Control Names

Control names are used in the rangebind and rangescale commands to specify the control (eg, button, stick, trigger, hat, etc.) that information is being read from. There are two basic types of controls: 1) special control names that begin with the characters "##", and 2) device-dependant control names that are specific names that are used by DirectInput.

## Control Names

The ## control names are not passed directly to DirectInput. They are similar to wildcards in that they allow you to ask for something generic like the x-axis of your joystick without having to know the precise name of the control (eg, x-axis vs. x axis vs. xaxis vs. x-achses). This means that ## control names should be device and manufacturer independent.

The possible ## control names are:

##x-axis | typically a horizontal axis
##y-axis | typically a vertical axis
##z-axis | typically a "twist" axis
##button 0 | the primary button control
##button 1 | the primary button control
##button 2 | the primary button control
##slider 0 | a slider control
##slider 1 | another slider control
##POV 0 | the primary POV hat
##POV 1 | the primary POV hat
##POV 2 | the primary POV hat
##POV 3 | the primary POV hat

Device-dependent control names

Device-dependant control names can vary depending on the manufacturer of the device you are using. These control names are typically names such as "button a" or "button 0" or "x" or "x-axis". You may need to check with your manufacturer to get the exact control names.

Analog Actions

These action names are specified in the File Header section of a JOYSTICK.CFG file. The are four different game actions that can be controlled with analog input.

AxisYaw

This action controls turning left or right. The higher the analog value, the faster you turn. Positive values turn to the right, negative values turn to the left. A value of zero means no movement.

AxisPitch

This action controls looking up or down. In regular mode this works much like turning left or right. The higher the value input to the game, the faster your view moves up or down. A positive value moves the view up and a negative value moves the view down. A value of zero means no movement. In fixed mode, which can be set using the FixedAxisPitch variable, the view angle is directly tied to the analog value being read by the game.

AxisForwardBackward

This action controls forward and backward movement. The higher the analog value the faster the movement. A positive value moves you forward, a negative value moves you backward. A value of zero means no movement. If you are in run mode your maximum speed (highest value) will be run speed. If you are in walk mode then your maximum speed (highest value) will be walk speed. This movement style is considerably different from normal movement in Shogo, which is digital (i.e., digital movement means that you are either stopped, running or walking--there is no movement speed between walking and running).

AxisLeftRight

This action controls left strafe and right strafe movement. The higher the analog value the faster the movement. A positive value moves you to the right, a negative value moves you to the left. A value of zero means no movement.

Shogo Digital Actions

These actions can be used in a rangebind command to activate the game event described below.

FragCount | a momentary key that displays the frag count screen
MouseAim | a momentary key that enables mouse aiming
CursorTog | Toggles the crosshair
InterfaceToggle | Toggles the Heads Up Display (this was disabled in all versions except 1.0)
ShowOrdinance | a momentary key that displays the Ordinance screen
CenterView | Centers the view
ChaseView | Switches the camera to "chase" or "3rd person" perspective
SendMessage | Enter chat mode
Weapon_9 | select weapon 9
Weapon_8 | Select weapon 8
Weapon_7 | Select weapon 7
Weapon_6 | Select weapon 6
Weapon_5 | Select weapon 5
Weapon_4 | Select weapon 4
Weapon_3 | Select weapon 3
Weapon_2 | Select weapon 2
Weapon_1 | Select weapon 1
Weapon_0 | Select weapon 0
NextWeapon | Select next weapon
PrevWeapon | Select previous weapon
VehicleModeToggle | Toggle vehicle mode
TractorBeam | Use the tractor beam
DoubleJump | execute a double jump
TurnAround | Turn around 180 degrees
Duck | duck.
Jump | jump.
Fire | Fire current weapon
Right | Turn to the right
Left | Turn to the left
Backward | Move backwards
Forward | Move forward
Strafe | modifies Left and Right to StrafeLeft and StrafeRight
Speed | a momentary key that enables run speed
RunLock | Stay in run mode permanently
StrafeLeft | side step to the left
StrafeRight | side step to the right
LookUp | Move view angle up
LookDown | Move view angle down
ScreenShot | Take a screenshot
QuickSave | Do a quicksave
QuickLoad | Do a quickload
DecScreenRect | Reduce the screen size
IncScreenRect | Increase the screen size

How to Set Up Buttons

Joystick buttons are assigned to an action by using the rangebind command. Use 0.0 for <low range value> and <high range value>.

An example of setting Button 0 on the joystick to the Fire action:
rangebind "Joystick 1" "Button 0" 0.000000 0.000000 "Fire"

How to Set Up Analog Left/Right Turning

To set up analog left-right turning, use rangebind and rangescale commands to the AxisYaw analog action. The dead zone for the AxisYaw action should also be set using the AxisYawDeadzone variable.

One example of how the commands could be used to set up analog left-right turning:
rangebind "Joystick 1" "##X-axis" 0.000000 0.000000 "AxisYaw"
rangescale "Joystick 1" "##X-axis" 0.100000 -1.000000 1.0000000 0.000000
AxisYawDeadzone 0.01

Here's the formatting for reference:
rangebind "<device name>" "<control name>" "<low range value>" "<high range value>" "<action name>"
rangescale "<device name>" "<control name>" "<scale value>" "<min range scale value>" "<max range scale value>" "<pre center offset value>"
<variable name> <numerical value>

Note that the range values passed into the rangebind command must both be 0.0.

The <scale value> that is passed into the rangescale command should be a small number--usually between 0.05 and 0.5. The larger the scale value the more sensitive the input will be. If you are using an input device other than a Joystick (such as a track ball) you may need to use larger values (eg, 1.0 or 1.5).

The <min range scale value> and < max range scale value> must be either -1.0 and 1.0 or 1.0 and -1.0, and should never be set to anything else. To invert the axis, flip the ordering to 1.0 and -1.0. If you need to swap left and right movement then try inverting the axis.

The <pre center offset value> passed into the rangescale command should usually be 0.0. For some devices (such as track balls) this value should set to 100.0 to offset a center value that is off by 100.0.

The AxisYawDeadzone is the threshold size of the input values before they are used. The dead zone should always be smaller than the <scale value>. A good dead zone value is usually about 10% of the <scale value> that is passed in. The larger the dead zone the more you will have to move the joystick before anything happens. If you are using an input device such as a trackball, the dead zone should be set to 0.0.

How to Set Up Digital Left/Right Turning

To set up digital left/right turning, use a rangebind command to the Left and Right actions. The ranges that will activate the left and right movement are used in the rangebind command. A rangescale command should be set up exactly like analog movement, although the scale should always be 1.0.

An example of a command that will enable digital left/right turning:
rangebind "Joystick 1" "##X-axis" 0.1999 1.001 "Right" -0.1999 -1.001 "Left"
rangescale "Joystick 1" "##X-axis" 1.000000 -1.000000 1.000000 0.000000

Here's the formatting for reference:
rangebind "<device name>" "<control name>" "<low range value>" "<high range value>" "<action name>"
rangescale "<device name>" "<control name>" "<scale value>" "<min range scale value>" "<max range scale value>" "<pre center offset value>"

Note that there is no variable to adjust the dead zone, because the dead zone is adjusted by changing the <low range value> and <high range value>. The closer these values are to zero, the smaller the dead zone becomes.

How to Set Up Analog Look Up/Look Down

To set up analog look up/look down, use rangebind and rangescale commands to the AxisPitch analog action. The dead zone for the AxisPitch action should also be set using the AxisPitchDeadzone variable.

An example of the commands that could be used to set up analog look up/look down:
rangebind "Joystick 1" "##Y-axis" 0.000000 0.000000 "AxisPitch"
rangescale "Joystick 1" "##Y-axis" 0.100000 -1.000000 1.0000000 0.000000
AxisPitchDeadzone 0.01

Here's the formatting for reference:
rangebind "<device name>" "<control name>" "<low range value>" "<high range value>" "<action name>"
rangescale "<device name>" "<control name>" "<scale value>" "<min range scale value>" "<max range scale value>" "<pre center offset value>"
<variable name> <numerical value>

The dead zone, rangebind and rangescale parameters are all set up the same way as described in the analog left/right turning section.

There is another option available for looking up and down called the FixedAxisPitch variable. If this variable is set to 1.0, then the viewing angle for looking up and down will be hard-wired to the position of the joystick. If the joystick is moved all the way in one direction, the view will be looking straight up. If the joystick is moved all the way in the opposite direction, the view will be looking straight down. If the axis is in the center, the view will be looking straight ahead.

When using the FixedAxisPitch option, the scale value passed to rangescale should always be set to 1.570796, or the view will not work properly.

Here is an example of the commands to use when using the FixedAxisPitch option. Note that the dead zone is 10% of the <scale value>:
FixedAxisPitch 1.0
rangebind "Joystick 1" "##Y-axis" 0.000000 0.000000 "AxisPitch"
rangescale "Joystick 1" "##Y-axis" 1.570796 -1.000000 1.000000
AxisPitchDeadzone 0.157

Here's the formatting for reference:
rangebind "<device name>" "<control name>" "<low range value>" "<high range value>" "<action name>"
rangescale "<device name>" "<control name>" "<scale value>" "<min range scale value>" "<max range scale value>" "<pre center offset value>"
<variable name> <numerical value>

How to Set Up Digital Look Up/Down

Digital Look Up/Down works just like digital left/right turning except that the action names are LookUp and LookDown.

An example of how to set up digital look up/down:
rangebind "Joystick 1" "##Y-axis" 0.1999 1.001 "LookDown" -0.1999 -1.001 "LookUp"
rangescale "Joystick 1" "##Y-axis" 1.000000 -1.000000 1.000000 0.000000

Here's the formatting for reference:
rangebind "<device name>" "<control name>" "<low range value>" "<high range value>" "<action name>"
rangescale "<device name>" "<control name>" "<scale value>" "<min range scale value>" "<max range scale value>" "<pre center offset value>"
Note that you can invert the LookUp/LookDown by changing the ordering of the <low range value> and <high range value>.

How to Set Up Analog Forward/Backward Movement

To set up analog forward/backward movement, use rangebind and rangescale commands to the AxisForwardBackward, Forward, and Backward actions. The dead zone for the AxisForwardBackward action should also be set using the AxisForwardBackwardDeadzone variable.

The dead zone and rangescale parameters are both set up the same way as described in the analog left right turning section.

The rangebind command is the same as analog left right turning, except that this rangebind has two additional actions bound to it. In this case, the Forward and Backward actions must be added to the rangebind command. Note that these actions should have low ranges equal to the dead zone value and negative the dead zone value. They should have high ranges equal to 1.0 and -1.0.

An example of the commands that could be used to set up analog forward/backward movement:
rangebind "Joystick 1" "##Y-axis" 0.000000 0.000000 "AxisForwardBackward" 0.100000 1.000000 "Forward" -0.100000 -1.00000 "Backward"
rangescale "Joystick 1" "##Y-axis" 1.000000 1.000000 -1.000000 0.000000
AxisForwardBackwardDeadzone 0.10

Here's the formatting for reference:
rangebind "<device name>" "<control name>" "<low range value>" "<high range value>" "<action name>"
rangescale "<device name>" "<control name>" "<scale value>" "<min range scale value>" "<max range scale value>" "<pre center offset value>"
<variable name> <numerical value>

How to Set Up Digital Forward/Backward Movement

Digital Forward/Backward Movement works just like digital LookUp/LookDown, except that the action names are Forward and Backward.

An example of how to set up digital forward/backward movement:
rangebind "Joystick 1" "##Y-axis" 0.1999 1.001 "Forward" -0.1999 -1.001 "Backward"
rangescale "Joystick 1" "##Y-axis" 1.000000 -1.000000 1.000000 0.000000

Here's the formatting for reference:
rangebind "<device name>" "<control name>" "<low range value>" "<high range value>" "<action name>"
rangescale "<device name>" "<control name>" "<scale value>" "<min range scale value>" "<max range scale value>" "<pre center offset value>"

How to Set Up Analog Left Right Strafe

To set up analog left/right strafing movement, use rangebind and rangescale commands to the AxisLeftRight, StrafeLeft, and StrafeRight actions. The dead zone for the AxisLeftRight action should also be set using the AxisLeftRightDeadzone variable.

All the commands work the same as the analog forward backward movement except for the different actions names and variable names.

An example of the commands that could be used to set up analog left/right strafe:
rangebind "Joystick 1" "##X-axis" 0.000000 0.000000 "AxisLeftRight" 0.1999 1.001 "StrafeRight" -0.1999 -1.001 "StrafeLeft"
rangescale "Joystick 1" "##X-axis" 1.000000 -1.000000 1.000000
AxisLeftRightDeadzone 0.2

Here's the formatting for reference:
rangebind "<device name>" "<control name>" "<low range value>" "<high range value>" "<action name>"
rangescale "<device name>" "<control name>" "<scale value>" "<min range scale value>" "<max range scale value>" "<pre center offset value>"

How to Set Up Digital Left/Right Strafe

To set up digital left/right strafing, use a rangebind command to the StrafeLeft and StrafeRight actions. The ranges that will activate the left and right movement are used in the rangebind command. A rangescale command should be set up exactly like analog movement, although the scale should always be 1.0.

Here is an example of a command that will enable digital left/right strafing:
rangebind "Joystick 1" "##X-axis" 0.1999 1.001 "StrafeRight" -0.1999 -1.001 "StrafeLeft"
rangescale "Joystick 1" "##X-axis" 1.000000 -1.000000 1.000000 0.000000

Here's the formatting for reference:
rangebind "<device name>" "<control name>" "<low range value>" "<high range value>" "<action name>"
rangescale "<device name>" "<control name>" "<scale value>" "<min range scale value>" "<max range scale value>" "<pre center offset value>"

Note that there is no variable to adjust the dead zone, because the dead zone is adjusted by changing the <low range value> and <high range value>. The closer these values are to zero, the smaller the dead zone becomes.

This works just like digital left right turning except that the action names to use are StrafeLeft and StrafeRight.

Using the POV Hat

A POV Hat returns values between 0 - 36000. Starting from the up position (0/36000) going around in a clockwise direction (9000 at 3 o'clock, 18000 at 6 o'clock, 27000 at 9 o'clock). Using the rangebind command, you can set up various digital actions so that they are activated when the hat is placed in different positions around the clock.

Some joysticks have a POV hat that returns the full range of possible numbers (eg, 17459), while others can only return four different values corresponding to the up (36000) , right (9000), down (18000) and left (27000) positions of the hat. There may also be other variations that fall in between.

An example of a hat configuration that does a jump when the hat is pointing up, a NextWeapon when the hat is to the right, a Duck when the hat is down, and a PrevWeapon when the hat is to the left:
rangebind "Joystick 1" "##pov 0" 0.0 1000.0 "Jump" 8000.0 10000.0 "NextWeapon" 17000.0 19000.0 "Duck" 26000 28000 "PrevWeapon"

Here's the formatting for reference:
rangebind "<device name>" "<control name>" "<low range value>" "<high range value>" "<action name>"

Using the Mouse Wheel

Although the mouse wheel is not really a joystick control, it can be added to a JOYSTICK.CFG file.

An example of a mouse wheel set up to select the next and previous weapons:
rangebind "##mouse" "Wheel" 0.100000 10000.000000 "NextWeapon" -10000.000000 -0.100000 "PrevWeapon"

Note that this uses ##mouse as the <device name> and "Wheel" as the <control name>. The control name "Wheel" should work for most mice, but may not work on all wheel mice. If Wheel doesn't work for your mouse, check out your mouse manufacturer for more information. Once you have the device and control name specified, you can then specify digital actions the same way that you would for any other control.

2-19-1999

Monolith Productions, Inc.

Where's the LUV? You know where…

MONOLITH