Visit the JFShadowWarrior website for the latest information. The source code for JFShadowWarrior can be found in this Git repository.

# System Requirements

At minimum, you need:

- 64-bit Intel, AMD, or compatible CPU
- OpenGL 2.1 capable GPU
- (Windows) Vista or newer (7, 8, 10+)
- (Mac) macOS 10.15 (Catalina) or newer

Additionally, these platforms and architectures are supported when building from source code:

- 32-bit Intel/AMD, and 32 or 64-bit ARM CPUs
- OpenGL ES 2.0 capable GPUs, e.g. Broadcom VideoCore IV (tested with Raspberry Pi 3 B+)

# Installation and Setup

After unzipping the JFShadowWarrior package somewhere on your computer, run the main executable: `JFShadowWarrior.app` on macOS, `sw.exe` on Windows. You ought to see the startup window open at the Game tab.

Windows, Linux and BSD (if built with GTK support) have similar startup windows with the same options.

You will now need to import the game data from a commercial release or the shareware version of Shadow Warrior as the game will not work without it.

1. Click the "Choose a location..." button, then navigate to a location where Shadow Warrior data can be found.
2. Choose a folder and JFShadowWarrior will then scan the location you've selected, copying any compatible game data it finds.

Where game data files are stored by JFShadowWarrior depends on the operating system you are using:

- (Linux, shared with all users) `/usr/local/share/games/jfsw`
- (Linux, single user) `~/.jfsw`
- (macOS, single user) `~/Library/Application Support/JFShadowWarrior`
- (Windows) wherever you've put sw.exe

Below are known locations of Shadow Warrior game data for various sources:

MS DOS Registered version CD-ROM
  In the `SWINST` directory of the disc.
Classic Redux from GOG on macOS
  To be determined.
Classic Redux from Steam on macOS
  In Steam, go to Shadow Warrior Classic Redux, open the 'gear' menu, choose Manage > Browse local files. Make note of this location to use for importing.
Classic Redux from Humble
  To be determined.
Classic Complete from GOG.com on macOS
  In GOG Galaxy 2, go to Shadow Warrior Classic Complete, open the 'options' menu (beside Play), choose Manage installation > Show folder. Make note of this location to use for importing.
Classic (1997) from Steam on macOS
  In Steam, go to Shadow Warrior Classic (1997), open the 'gear' menu, choose Manage > Browse local files. Make note of this location to use for importing.
MS DOS Shareware version

  If you have downloaded an original 3D Realms distribution file named `3DSW12.ZIP`:

  1. Unzip `3DSW12.ZIP` to obtain the `SWSW12.SHR` file.
  2. Rename `SWSW12.SHR` to `SWSW12.ZIP`, then unzip it.

  Alternatively, you can fetch swsw12.zip authenticity-intact from my site ready to unzip and point JFShadowWarrior at for importing.

## CD Music

Music from the retail Shadow Warrior CD can be ripped and encoded to Ogg Vorbis format files, and JFShadowWarrior can play those files in place of having the original game CD in the system CD drive. Each track should be named `trackNN.ogg`, NN being the track number 0-padded to two digits, and placed beside the `sw.grp` file in the game data location mentioned above.

## "Portable" Installation

Typically the game will store its configuration information and saved games in a private location for your user account:

- (Linux) `~/.jfsw`
- (macOS) `~/Library/Application Support/JFShadowWarrior`
- (Windows) `C:\Users\your-name\AppData\JFShadowWarrior`

To have the game instead store these files in the working directory where the game was started, create an empty file named `user_profiles_disabled` (no extension) beside the executable. You can put the `sw.grp` file in the same location, thus making everything self-contained and 'portable'.

# Multiplayer

Multiplayer games can be started from the startup window, or for more specialised situations, with command-line parameters passed to the game.

From the startup window, one player should choose "Host multi-player game" and select the number of players, then press Start to begin waiting. The other players should choose "Join multi-player game" and enter the hostname or IP address of the system hosting the game, and then press Start. The game will proceed once all players are joined.

Windows, Linux and BSD (if built with GTK support) have similar startup windows with the same options.

The game communicates on UDP port 23513 by default, so if you intend to play across the Internet you may need to forward that port through relevant firewalls of the system hosting the game.

## Command-line launching

The general command line syntax to use on each platform is:

- (Linux, in a terminal) `/path/to/jfsw/sw [options] -net [net options]`
- (macOS, from a Terminal window) `open /Path/To/JFShadowWarrior.app --args [options] -net [net options]`
- (Windows, from a Command Prompt window) `x:\path\to\jfsw\sw.exe [options] -net [net options]`

Multiplayer games can use either of two communication modes: hosted (a.k.a. master/slave mode) and peer-to-peer. Peer-to-peer is more difficult to use over the Internet and more troublesome to correctly configure. In all modes you must know the exact number of players as the game will not start until all players are present.

## Hosted (master/slave) mode

Choose a system to be the host of the game, and each other player will connect to that host.

The "net options" for this mode are:

- `-pportnum` — host the game on a different UDP port to the default 23513.
- `-nm` — be host of a 2-player game.
- `-nm:num` — be host of a num-player game.
- `-nm host-name-or-ip` — join a game hosted by host-name-or-ip.
- `-nm host-name-or-ip:port` — join a game hosted by host-name-or-ip on non-default port port.

For example, a three-player hosted game is launched like so:

1. (Player 1, hosts) `sw -name Player1 -net -nm:3`
2. (Player 2, joins) `sw -name Player2 -net -nm host1`
3. (Player 3, joins) `sw -name Player3 -net -nm host1`

## Peer-to-peer mode

In this mode each player sends data to each other player in the game directly, which is only really practical in non-firewalled LAN-like environments. The list of peers specified on the command line must be consistently ordered amongst all players, and each peer will launch the game with slightly different options.

The "net options" for this mode are:

- `-pportnum` — communicate with other peers on a different UDP port to the default 23513.
- `-np ordered-peer-list…` — participate in a peer-to-peer game.
- `.` or `*` — identify the local machine in the ordered peer list.
- `host-name-or-ip` — identify a peer at host-name-or-ip in the ordered peer list.
- `host-name-or-ip:port` — identify a peer at host-name-or-ip on non-default port port in the ordered peer list.

For example, a three-player peer-to-peer game is launched like so:

1. (Player 1) `sw -name Player1 -net -np . host2 host3`
2. (Player 2) `sw -name Player2 -net -np host1 . host3`
3. (Player 3) `sw -name Player3 -net -np host1 host2 .`

# Customisation File Format

Historically, modifications and total conversions for Shadow Warrior have been required to hack a copy of the game executable to replace the names of maps and the episode title information. JFShadowWarrior introduces a customisation script file that is loaded on startup to achieve the same end.

The customisation file should be named `swcustom.txt` and its contents may consist of the directives below. Comments can be used by prefixing the text with a `//` (C++ style), or surrounding the text with `/*` (comment here) `*/` (C style).

map number { ... }
level number { ... }
  Selects the map to change the information of. number is a value in the range of 1 to 29. Levels 1 to 4 are the shareware maps. level is a synonym for map. The brace-enclosed block may contain these directives:
  title title
  name title
  description title
    Sets the new title of the level to title. name and description are synonyms for title.
  filename filename
  file filename
  fn filename
  levelname filename
    Sets the new map file name to filename. file, fn, and levelname are synonyms for filename.
  song filename
  music filename
  songname filename
    Sets the new MIDI file name to filename. music and songname are synonyms for song.
  cdatrack tracknum
  cdtrack tracknum
    Sets the Red-Book CD track number to tracknum. cdtrack is a synonym for cdatrack.
  besttime seconds
  partime seconds
    Sets the "best" and "par" times of the level respectively. seconds is the new par time given as a count of seconds.
episode number { ... }
  Selects the episode to change the information of. number is a value in the range of 1 to 2. The brace-enclosed block may contain these directives:
  title title
  name title
  description title
    Sets the new title of the episode to title. name and description are synonyms for title.
  subtitle subtitle
    Sets the new subtitle of the episode to subtitle.
skill number { ... }
  Selects the skill level to change the information of. number is a value in the range of 1 to 4. The brace-enclosed block may contain this directive:
  title title
  name title
  description title
    Sets the new title of the skill level to title. name and description are synonyms for title.
inventory number { ... }
  Selects the inventory item to change the information of. number is either a symbol or number from this table. It is recommended that the symbolic names be used rather than the numeric codes.

  Symbol | Number | Inventory item
  --- | --- | ---
  INV_ARMOR | 1 | Conventional armour vest
  INV_KEVLAR | 2 | Kevlar armour vest
  INV_SM_MEDKIT | 3 | Pickup medkit
  INV_FORTUNE | 4 | Fortune cookie
  INV_MEDKIT | 5 | Portable medkit
  INV_GAS_BOMB | 6 | Gas bomb
  INV_FLASH_BOMB | 7 | Flash bomb
  INV_CALTROPS | 8 | Caltrops
  INV_NIGHT_VIS | 9 | Night vision goggles
  INV_REPAIR_KIT | 10 | Repair kit
  INV_SMOKE_BOMB | 11 | Smoke bomb

  The brace-enclosed block may contain these directives:

  title title
  name title
  description title
    Sets the new name of the inventory item to title. name and description are synonyms for title.
  amount amount
    Sets the quantity of the item that will be added to the player's inventory.
weapon number { ... }
  Selects the weapon to change the information of. number is either a symbol or number from this table. It is recommended that the symbolic names be used rather than the numeric codes.

  Symbol | Number | Weapon name | Customisable properties (see note 1)
  --- | --- | --- | ---
  WPN_FIST | 1 | Fists | damage
  WPN_SWORD | 2 | Sword | damage
  WPN_SHURIKEN | 3 | Shurikens | weapon name and pickup, damage
  WPN_STICKYBOMB | 4 | Sticky bombs | weapon name and pickup, damage
  WPN_UZI | 5 | Uzi submachine gun | weapon/ammo name and pickup, damage
  WPN_MISSILE | 6 | Rocket launcher | weapon/ammo name and pickup, damage
  WPN_NUKE | 7 | Nuclear warhead, heat seeker card (see note 2) | weapon/ammo name and pickup, damage
  WPN_GRENADE | 8 | Grenade launcher | weapon/ammo name and pickup, damage
  WPN_RAILGUN | 9 | Rail gun | weapon/ammo name and pickup, damage
  WPN_SHOTGUN | 10 | Riot gun | weapon/ammo name and pickup, damage
  WPN_HOTHEAD | 11 | Guardian head | weapon name and pickup, damage
  WPN_HEART | 12 | Ripper heart | weapon name and pickup, damage
  WPN_HOTHEAD_NAPALM | 13 | Guardian head napalm (secondary attack) | damage
  WPN_HOTHEAD_RING | 14 | Guardian head ring (tertiary attack) | damage

  Note 1: Only some properties of particular weapons can be changed. Changing other properties not mentioned in the table will have no effect.

  Note 2: The heat seeker card name and pickup amount is stored as the ammunition information of the nuclear warhead.

  The brace-enclosed block may contain these directives:

  title title
  name title
  description title
    Sets the new name of the weapon to title. name and description are synonyms for title.
  ammoname name
    Sets the new name of the ammunition for the weapon to name.
  maxammo amount
    Sets the maximum amount of ammunition that can be carried for the weapon to amount.
  mindamage min
  maxdamage max
    Sets the minimum and/or maximum damage factors for the weapon to min and max respectively.
  pickup amount
    Sets the amount of ammunition to be added when picking up ammunition for the weapon to amount.
  weaponpickup amount
    Sets the amount of ammunition to be added when picking up the weapon to amount.

Here is a fictitious example:

    level 1 {
        title    "My Neat Map"
        filename "neatmap.map"
        song     "coolsong.mid"
        cdatrack 4
        besttime 1800    // half an hour
        partime  3600    // an hour
    }

    episode 1 {
        title    "My Neat Episode"
        subtitle "One level of lameness"
    }

    skill 1 {
        title  "Don't hurt me"
    }

    inventory INV_ARMOR {
        name   "Chain mail"
        amount 25
    }

    weapon WPN_UZI {
        name      "Pea shooter"
        ammoname  "Pebbles"
        maxammo   500
        mindamage 1
        maxdamage 2
        pickup    100
        weaponpickup 25
    }

# Console Commands

This is a list of more useful console commands and settings and their purpose:

clear
  Clear the console.
glinfo
  Displays some information about the OpenGL driver. Use "glinfo exts" to display supported OpenGL extensions.
glmultisample <0, 1, 2, …>
  Enable OpenGL multisample antialiasing. 0 disables it. You need to use "restartvid" to apply any changes to this value.
gltextureanisotropy <level>
  Sets the OpenGL anisotropic filtering level. The default is the highest level supported by the hardware.
gltexturemode <mode-number>
  Sets the OpenGL texturing mode. Valid values are:

  0 | GL_NEAREST
  1 | GL_LINEAR
  2 | GL_NEAREST_MIPMAP_NEAREST
  3 | GL_LINEAR_MIPMAP_NEAREST (bilinear)
  4 | GL_NEAREST_MIPMAP_LINEAR (gives an unfiltered appearance like the original software renderer)
  5 | GL_LINEAR_MIPMAP_LINEAR (trilinear, the default)

glusetexcompr <0 or 1>
  Enables or disables the use of OpenGL texture compression for replacement textures. You need to use "restartvid" to apply any changes to this value.
help <name>
  Displays a help message for a particular console variable or command.
listsymbols
  Displays the names of all commands and variables available in the console.
novoxmips <0 or 1>
  Disables or enables the use of voxel mipmaps to improve voxel visual quality.
osdrows <num>
  Sets the number of visible lines of the console when it is open.
restartvid
  Reinitialise video to apply settings changes.
screencaptureformat <0 or 1 or 2>
  0 = Targa, 1 = PCX, 2 = PNG (default)
usegammabrightness <0 or 1 or 2>
  Set brightness in one of several ways. 0 = palette-based, 1 = shader-based (default), 2 = system gamma. System gamma will brighten the whole display when in windowed mode.
usegoodalpha <0 or 1>
  If 1, a lower alpha cutoff value is used when rendering textures with transparency, which gives better looking transparent textures at the expense of some sprites behind the transparent item potentially being invisible in certain circumstances. 0 is a more compatible value (and is the default) for this option but slight visual degradation will result.
vidmode <bpp>
vidmode <xdim> <ydim> [bpp [fs [display]]]
  Change the video mode. xdim ydim are the resolution. bpp is the colour depth (8, 16, 24, 32). fs is 0 for windowed, 1 for fullscreen. display is a display number for fullscreen mode, with 0 being the primary display.
maxrefreshfreq <0 or freq>
  Set the highest display refresh frequency for fullscreen OpenGL modes. 0 is the default representing 'no maximum'.

# Artistic Credits

Game icon, and editor and game startup banners
  By Jonathon Fowler. The yin-yang symbol that forms the basis of the icon was originally by Multimotyl and was sourced from openclipart.org.
Editor icon
  By Jonathon Fowler. The LCD display that forms the basis of the icon was originally by Sergio Luiz Araujo Silva and was sourced from openclipart.org.

# License

JFShadowWarrior is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

The JFBuild engine used in JFShadowWarrior is used under the terms of the BUILD Source Code License.