code:
#include "build.h"
#include "baselayer.h"

#ifdef _WIN32
# include "windows_inc.h"
# include "winbits.h"
#elif defined __APPLE__
# include "osxbits.h"
#endif

#include "common.h"
#include "common_game.h"
#include "grpscan.h"

uint8_t SW_GameFlags;

static const char *defaultgrpfilename = "SW.GRP";
static const char *defaultdeffilename = "sw.def";

// g_grpNamePtr can ONLY point to a malloc'd block (length BMAX_PATH)
char *g_grpNamePtr = NULL;

void clearGrpNamePtr(void)
{
    Xfree(g_grpNamePtr);
    // g_grpNamePtr assumed to be assigned to right after
}

const char *G_DefaultGrpFile(void)
{
    return defaultgrpfilename;
}
const char *G_GrpFile(void)
{
    if (g_grpNamePtr == NULL)
        return G_DefaultGrpFile();
    else
        return g_grpNamePtr;
}

const char *G_DefaultDefFile(void)
{
    return defaultdeffilename;
}
const char *G_DefFile(void)
{
    if (g_defNamePtr == NULL)
        return G_DefaultDefFile();
    else
        return g_defNamePtr;
}

void SW_InitMultiPsky(void)
{
    // default
    psky_t * const defaultsky = tileSetupSky(DEFAULTPSKY);
    defaultsky->lognumtiles = 1;
    defaultsky->horizfrac = 8192;
}

int g_useCwd;
static char g_rootDir[BMAX_PATH];

void SW_ExtPreInit(int32_t argc, char const * const * argv)
{
    g_useCwd = G_CheckCmdSwitch(argc, argv, "-usecwd");

#ifdef _WIN32
    GetModuleFileName(NULL,g_rootDir,BMAX_PATH);
    Bcorrectfilename(g_rootDir,1);
    //buildvfs_chdir(g_rootDir);
#else
    buildvfs_getcwd(g_rootDir,BMAX_PATH);
    strcat(g_rootDir,"/");
#endif
}

#ifndef EDUKE32_STANDALONE

#if defined _WIN32 || defined __linux__ || defined EDUKE32_BSD || defined EDUKE32_OSX
static int32_t SW_Add_GOG_SWCR(const char * path)
{
    char buf[BMAX_PATH];

    addsearchpath_user(path, SEARCHPATH_REMOVE);
    Bsnprintf(buf, sizeof(buf), "%s/addons", path);
    addsearchpath_user(buf, SEARCHPATH_REMOVE);
    Bsnprintf(buf, sizeof(buf), "%s/music", path);
    return addsearchpath(buf);
}
static int32_t SW_Add_GOG_SWCC(const char * path)
{
    char buf[BMAX_PATH];

    addsearchpath_user(path, SEARCHPATH_REMOVE);
    Bsnprintf(buf, sizeof(buf), "%s/MUSIC", path);
    return addsearchpath(buf);
}
#endif

#if defined __linux__ || defined EDUKE32_BSD
static void SW_Add_GOG_SWCR_Linux(const char * path)
{
    char buf[BMAX_PATH];

    Bsnprintf(buf, sizeof(buf), "%s/game", path);
    SW_Add_GOG_SWCR(buf);
}
static void SW_Add_GOG_SWCC_Linux(const char * path)
{
    char buf[BMAX_PATH];

    Bsnprintf(buf, sizeof(buf), "%s/data", path);
    SW_Add_GOG_SWCC(buf);
}
#endif

#ifndef EDUKE32_TOUCH_DEVICES
#if defined EDUKE32_OSX || defined __linux__ || defined EDUKE32_BSD
static void SW_AddSteamPaths(const char *basepath)
{
    char buf[BMAX_PATH];

    // Shadow Warrior Classic Redux - Steam
    static char const s_SWCR_Steam[] = "steamapps/common/Shadow Warrior Classic/gameroot";
    Bsnprintf(buf, sizeof(buf), "%s/%s", basepath, s_SWCR_Steam);
    addsearchpath_user(buf, SEARCHPATH_REMOVE);
    Bsnprintf(buf, sizeof(buf), "%s/%s/addons", basepath, s_SWCR_Steam);
    addsearchpath_user(buf, SEARCHPATH_REMOVE);
    Bsnprintf(buf, sizeof(buf), "%s/%s/classic/MUSIC", basepath, s_SWCR_Steam);
    if (addsearchpath(buf) == 0)
        return;

    // Shadow Warrior Classic (1997) - Steam
    static char const s_SWC_Steam[] = "steamapps/common/Shadow Warrior Original/gameroot";
    Bsnprintf(buf, sizeof(buf), "%s/%s", basepath, s_SWC_Steam);
    addsearchpath_user(buf, SEARCHPATH_REMOVE);
    Bsnprintf(buf, sizeof(buf), "%s/%s/MUSIC", basepath, s_SWC_Steam);
    if (addsearchpath(buf) == 0)
        return;

    // Shadow Warrior (Classic) - 3D Realms Anthology - Steam
#if defined EDUKE32_OSX
    Bsnprintf(buf, sizeof(buf), "%s/steamapps/common/Shadow Warrior DOS/Shadow Warrior.app/Contents/Resources/sw", basepath);
    addsearchpath(buf);
#endif
}
#endif
#endif
#endif

static void SW_AddSearchPaths()
{
#ifndef EDUKE32_STANDALONE
#ifndef EDUKE32_TOUCH_DEVICES
#if defined __linux__ || defined EDUKE32_BSD
    char buf[BMAX_PATH];
    char *homepath = Bgethomedir();

    Bsnprintf(buf, sizeof(buf), "%s/.steam/steam", homepath);
    SW_AddSteamPaths(buf);

    Bsnprintf(buf, sizeof(buf), "%s/.steam/steam/steamapps/libraryfolders.vdf", homepath);
    Paths_ParseSteamLibraryVDF(buf, SW_AddSteamPaths);

    // Shadow Warrior Classic Redux - GOG.com
    Bsnprintf(buf, sizeof(buf), "%s/GOG Games/Shadow Warrior Classic Redux", homepath);
    SW_Add_GOG_SWCR_Linux(buf);
    Paths_ParseXDGDesktopFilesFromGOG(homepath, "Shadow_Warrior_Classic_Redux", SW_Add_GOG_SWCR_Linux);

    // Shadow Warrior Classic Complete - GOG.com
    Bsnprintf(buf, sizeof(buf), "%s/GOG Games/Shadow Warrior Classic Complete", homepath);
    SW_Add_GOG_SWCC_Linux(buf);
    Paths_ParseXDGDesktopFilesFromGOG(homepath, "Shadow_Warrior_Classic_Complete", SW_Add_GOG_SWCC_Linux);

    Xfree(homepath);

    addsearchpath("/usr/share/games/jfsw");
    addsearchpath("/usr/local/share/games/jfsw");
    addsearchpath("/usr/share/games/voidsw");
    addsearchpath("/usr/local/share/games/voidsw");
#elif defined EDUKE32_OSX
    char buf[BMAX_PATH];
    int32_t i;
    char *applications[] = { osx_getapplicationsdir(0), osx_getapplicationsdir(1) };
    char *support[] = { osx_getsupportdir(0), osx_getsupportdir(1) };

    for (i = 0; i < 2; i++)
    {
        Bsnprintf(buf, sizeof(buf), "%s/Steam", support[i]);
        SW_AddSteamPaths(buf);

        Bsnprintf(buf, sizeof(buf), "%s/Steam/steamapps/libraryfolders.vdf", support[i]);
        Paths_ParseSteamLibraryVDF(buf, SW_AddSteamPaths);

        // Shadow Warrior Classic Complete - GOG.com
        Bsnprintf(buf, sizeof(buf), "%s/Shadow Warrior.app/Contents/Resources/Shadow Warrior.boxer/C swarrior_files.harddisk", applications[i]);
        SW_Add_GOG_SWCC(buf);
        Bsnprintf(buf, sizeof(buf), "%s/Shadow Warrior Complete/Shadow Warrior.app/Contents/Resources/Shadow Warrior.boxer/C swarrior_files.harddisk", applications[i]);
        SW_Add_GOG_SWCC(buf);
        Bsnprintf(buf, sizeof(buf), "%s/Shadow Warrior Complete.app/Contents/Resources/game/Shadow Warrior.app/Contents/Resources/Shadow Warrior.boxer/C swarrior_files.harddisk", applications[i]);
        SW_Add_GOG_SWCC(buf);

        // Shadow Warrior Classic Redux - GOG.com
        Bsnprintf(buf, sizeof(buf), "%s/Shadow Warrior Classic Redux.app/Contents/Resources/gameroot", applications[i]);
        SW_Add_GOG_SWCR(buf);
        Bsnprintf(buf, sizeof(buf), "%s/Shadow Warrior Classic Redux/Shadow Warrior Classic Redux.app/Contents/Resources/gameroot", applications[i]);
        SW_Add_GOG_SWCR(buf);
        Bsnprintf(buf, sizeof(buf), "%s/Shadow Warrior Classic Redux.app/Contents/Resources/game/Shadow Warrior Classic Redux.app/Contents/Resources/gameroot", applications[i]);
        SW_Add_GOG_SWCR(buf);
    }

    for (i = 0; i < 2; i++)
    {
        Bsnprintf(buf, sizeof(buf), "%s/JFSW", support[i]);
        addsearchpath(buf);
        Bsnprintf(buf, sizeof(buf), "%s/VoidSW", support[i]);
        addsearchpath(buf);
    }

    for (i = 0; i < 2; i++)
    {
        Xfree(applications[i]);
        Xfree(support[i]);
    }
#elif defined (_WIN32)
    char buf[BMAX_PATH] = {0};
    DWORD bufsize;

    // Shadow Warrior Classic Redux - Steam
    bufsize = sizeof(buf);
    if (Paths_ReadRegistryValue(R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 225160)", "InstallLocation", buf, &bufsize))
    {
        char * const suffix = buf + bufsize - 1;
        DWORD const remaining = sizeof(buf) - bufsize;

        Bstrncpy(suffix, "/gameroot", remaining);
        addsearchpath_user(buf, SEARCHPATH_REMOVE);
        Bstrncpy(suffix, "/gameroot/addons", remaining);
        addsearchpath_user(buf, SEARCHPATH_REMOVE);
        Bstrncpy(suffix, "/gameroot/classic/MUSIC", remaining);
        if (addsearchpath(buf) == 0)
            return;
    }

    // Shadow Warrior Classic (1997) - Steam
    bufsize = sizeof(buf);
    if (Paths_ReadRegistryValue(R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 238070)", "InstallLocation", buf, &bufsize))
    {
        char * const suffix = buf + bufsize - 1;
        DWORD const remaining = sizeof(buf) - bufsize;

        Bstrncpy(suffix, "/gameroot", remaining);
        addsearchpath_user(buf, SEARCHPATH_REMOVE);
        Bstrncpy(suffix, "/gameroot/MUSIC", remaining);
        if (addsearchpath(buf) == 0)
            return;
    }

    // Shadow Warrior Classic Redux - GOG.com
    bufsize = sizeof(buf);
    if (Paths_ReadRegistryValue(R"(SOFTWARE\GOG.com\Games\1618073558)", "PATH", buf, &bufsize))
    {
        if (SW_Add_GOG_SWCR(buf) == 0)
            return;
    }

    // Shadow Warrior Classic Complete - GOG.com
    bufsize = sizeof(buf);
    if (Paths_ReadRegistryValue(R"(SOFTWARE\GOG.com\Games\1207659142)", "PATH", buf, &bufsize))
    {
        if (SW_Add_GOG_SWCC(buf) == 0)
            return;
    }
    bufsize = sizeof(buf);
    if (Paths_ReadRegistryValue("SOFTWARE\\GOG.com\\GOGSHADOWARRIOR", "PATH", buf, &bufsize))
    {
        if (SW_Add_GOG_SWCC(buf) == 0)
            return;
    }

    // Shadow Warrior Classic Complete - ZOOM Platform
    bufsize = sizeof(buf);
    if (Paths_ReadRegistryValue(R"(SOFTWARE\ZOOM PLATFORM\Shadow Warrior Classic Complete)", "InstallPath", buf, &bufsize))
    {
        if (SW_Add_GOG_SWCC(buf) == 0)
            return;
    }

    // Shadow Warrior (Classic) - 3D Realms Anthology - Steam
    bufsize = sizeof(buf);
    if (Paths_ReadRegistryValue(R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 358400)", "InstallLocation", buf, &bufsize))
    {
        char * const suffix = buf + bufsize - 1;
        DWORD const remaining = sizeof(buf) - bufsize;

        Bstrncpy(suffix, "/Shadow Warrior", remaining);
        addsearchpath(buf);
    }

    // Shadow Warrior - 3D Realms Anthology
    bufsize = sizeof(buf);
    if (Paths_ReadRegistryValue("SOFTWARE\\3DRealms\\Shadow Warrior", NULL, buf, &bufsize))
    {
        char * const suffix = buf + bufsize - 1;
        DWORD const remaining = sizeof(buf) - bufsize;

        Bstrncpy(suffix, "/Shadow Warrior", remaining);
        addsearchpath(buf);
    }

    // 3D Realms Anthology
    bufsize = sizeof(buf);
    if (Paths_ReadRegistryValue("SOFTWARE\\3DRealms\\Anthology", NULL, buf, &bufsize))
    {
        char * const suffix = buf + bufsize - 1;
        DWORD const remaining = sizeof(buf) - bufsize;

        Bstrncpy(suffix, "/Shadow Warrior", remaining);
        addsearchpath(buf);
    }
#endif
#endif
#endif
}

void SW_CleanupSearchPaths()
{
    removesearchpaths_withuser(SEARCHPATH_REMOVE);
}

static inline void SW_AddMusicFolder()
{
#ifndef _WIN32
    if (addsearchpath("MUSIC") == 0)
        return;
#endif
    addsearchpath("music");
}

void SW_ExtInit()
{
    if (!g_useCwd)
        SW_AddSearchPaths();

#ifdef EDUKE32_OSX
    char *appdir = Bgetappdir();
    addsearchpath(appdir);
    Xfree(appdir);
#endif

    char cwd[BMAX_PATH];
#ifdef USE_PHYSFS
    strncpy(cwd, PHYSFS_getBaseDir(), ARRAY_SIZE(cwd));
    cwd[ARRAY_SIZE(cwd)-1] = '\0';
#else
    if (buildvfs_getcwd(cwd, ARRAY_SIZE(cwd)) && Bstrcmp(cwd, "/") != 0)
#endif
        addsearchpath(cwd);
#if defined(_WIN32) && !defined(EDUKE32_STANDALONE)
    if (buildvfs_exists("user_profiles_enabled"))
#else
    if (g_useCwd == 0 && !buildvfs_exists("user_profiles_disabled"))
#endif
    {
        char *homedir;
        int32_t asperr;

        if ((homedir = Bgethomedir()))
        {
            Bsnprintf(cwd, ARRAY_SIZE(cwd), "%s/"
#if defined(_WIN32)
                      APPNAME
#elif defined(GEKKO)
                      "apps/" APPBASENAME
#else
                      ".config/" APPBASENAME
#endif
                      ,homedir);
            asperr = addsearchpath(cwd);
            if (asperr == -2)
            {
                if (buildvfs_mkdir(cwd,S_IRWXU) == 0) asperr = addsearchpath(cwd);
                else asperr = -1;
            }
            if (asperr == 0)
                buildvfs_chdir(cwd);
            Xfree(homedir);
        }
    }

    SW_AddMusicFolder();

#ifndef EDUKE32_STANDALONE
    if (g_grpNamePtr == NULL)
    {
        const char *cp = getenv("SWGRP");
        if (cp)
        {
            clearGrpNamePtr();
            g_grpNamePtr = dup_filename(cp);
            initprintf("Using \"%s\" as main GRP file\n", g_grpNamePtr);
        }
    }
#endif
}

struct grpfile const * g_selectedGrp;

void SW_ScanGroups()
{
    ScanGroups();

    g_selectedGrp = NULL;

    char const * const currentGrp = G_GrpFile();

    for (grpfile_t const *fg = foundgrps; fg; fg=fg->next)
    {
        if (!Bstrcasecmp(fg->filename, currentGrp))
        {
            g_selectedGrp = fg;
            break;
        }
    }

    if (g_selectedGrp == NULL)
        g_selectedGrp = foundgrps;
}

static int32_t SW_TryLoadingGrp(char const * const grpfile, internalgrpfile const * type = nullptr)
{
    int32_t i;

    if ((i = initgroupfile(grpfile)) == -1)
        initprintf("Warning: could not find main data file \"%s\"!\n", grpfile);
    else
    {
        initprintf("Using \"%s\" as main game data file.\n", grpfile);
        if (type)
        {
            if (type->postprocessing)
                type->postprocessing(i);
            SW_GameFlags |= type->gameflags;
        }
    }

    return i;
}

static int32_t SW_LoadGrpDependencyChain(grpfile_t const * const grp)
{
    if (!grp)
        return -1;

    if ((grp->type->flags & GRP_HAS_DEPENDENCY) && grp->type->dependency != grp->type->crcval)
        SW_LoadGrpDependencyChain(FindGroup(grp->type->dependency));

    int32_t const i = SW_TryLoadingGrp(grp->filename, grp->type);

    return i;
}

int g_addonNum = -1;

void SW_LoadGroups()
{
    if (g_addonNum != -1)
        SW_LoadAddon();

    if (SW_LoadGrpDependencyChain(g_selectedGrp) != -1)
    {
        clearGrpNamePtr();
        g_grpNamePtr = dup_filename(g_selectedGrp->filename);
    }
    else
    {
        SW_TryLoadingGrp(G_GrpFile());
    }
}


code:
//-------------------------------------------------------------------------
/*
Copyright (C) 1997, 2005 - 3D Realms Entertainment

This file is part of Shadow Warrior version 1.2

Shadow Warrior 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.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

Original Source: 1997 - Frank Maddin and Jim Norwood
Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
*/
//-------------------------------------------------------------------------

//****************************************************************************
//
// common_game.h
//
// common defines for the setup program
//
//****************************************************************************

#ifndef common_public_
#define common_public_
#ifdef __cplusplus
extern "C" {
#endif

//****************************************************************************
//
// DEFINES
//
//****************************************************************************

#define APPNAME "VoidSW"
#ifndef APPBASENAME
#define APPBASENAME         "voidsw"
#endif

//
// Color Defines
//

#define MENUBACK_FOREGROUND COLOR_BLACK
#define MENUBACK_BACKGROUND COLOR_DARKGRAY

#define MENUBACKBORDER_FOREGROUND COLOR_BLACK
#define MENUBACKBORDER_BACKGROUND COLOR_GRAY

#define MENU_ACTIVE_FOREGROUND   COLOR_WHITE
#define MENU_INACTIVE_FOREGROUND COLOR_GRAY
#define MENU_DISPLAY_FOREGROUND  COLOR_LIGHTGREEN

#define MENU_SECTIONHEADER_FOREGROUND   COLOR_YELLOW

//
// Setup program defines
//

#define SETUPPROGRAMNAME ("Shadow Warrior Setup")
#define SETUPPROGRAMVERSION ("1.2")

#define GAMENAME "Shadow Warrior"
#define GAMELAUNCHER ("SW.EXE")
#define GAMETOTYPE ("SW")

#define MENUFOOTER "Esc Exits   Move  �� Selects\0"

#define COMMITLAUNCHER ("COMMIT.EXE")
#define COMMITFILENAME ("COMMIT.DAT")

#define MAXVOICES 32
#define SONGNAME ("Shadow Warrior Theme Song")
//#define SOUNDSETUPLAUNCHER ("SNDSETUP.EXE")

// Default Socket Number

#define DEFAULTSOCKETNUMBER 0x8849

// Default RTS file

#define DEFAULTRTSFILE "sw.rts"

// Default RTS path

#define DEFAULTRTSPATH ".\\"

// Default UserLevel path

#define DEFAULTLEVELPATH ".\\"

// Default External Control file

#define DEFAULTCONTROLFILE "EXTERNAL.EXE"

// Default Help file

#define DEFAULTHELPFILE "SWHELP.EXE"

// RTS extension

#define RTSEXTENSION "RTS"

// MAP extension

#define MAPEXTENSION "MAP"

// Default Player name

#define DEFAULTPLAYERNAME "KATO"

// Default Macros

#define MACRO1  "Burn baby burn..."
#define MACRO2  "You make another stupid move."
#define MACRO3  "Blocking with your head again?"
#define MACRO4  "You not fight well with hands!"
#define MACRO5  "You so stupid!"
#define MACRO6  "Quit jerking off. Come fight me!"
#define MACRO7  "What the matter you scaredy cat?"
#define MACRO8  "Did I break your concentration?"
#define MACRO9  "Hope you were paying attention."
#define MACRO10 "ITTAIIIUUU!!!"

enum
{
    GAMEFLAG_SHAREWARE = 1u<<0u,
    GAMEFLAG_SWWD = 1u<<1u,
    GAMEFLAG_SWTD = 1u<<2u,
};
extern uint8_t SW_GameFlags;

//#define SW_SHAREWARE 1     // This determines whether game is shareware compile or not!
#define SW_SHAREWARE (SW_GameFlags & GAMEFLAG_SHAREWARE)

extern struct grpfile const * g_selectedGrp;

extern int g_useCwd;

extern char *g_grpNamePtr;

const char *G_DefaultGrpFile(void);
const char *G_GrpFile(void);

void clearGrpNamePtr(void);

void SW_InitMultiPsky(void);

void SW_ExtPreInit(int32_t argc, char const * const * argv);
void SW_ExtInit(void);

void SW_ScanGroups(void);
void SW_LoadGroups(void);

void SW_CleanupSearchPaths(void);

enum searchpathtypes_t {
    SEARCHPATH_REMOVE = 1<<0,
};

extern int g_addonNum;

typedef enum basepal_ {
    BASEPAL = 0,
    DREALMSPAL,
    TITLEPAL,
    TENPAL,
    ANIMPAL,
    BASEPALCOUNT
} basepal_t;

#ifdef __cplusplus
};
#endif
#endif

repo_name: orochi/nblood

license: mit


code:
//-------------------------------------------------------------------------
/*
Copyright (C) 1997, 2005 - 3D Realms Entertainment

This file is part of Shadow Warrior version 1.2

Shadow Warrior 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.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

Original Source: 1997 - Frank Maddin and Jim Norwood
Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
*/
//-------------------------------------------------------------------------
#include "build.h"
#include "baselayer.h"
#include "osd.h"

#include "settings.h"
#include "mytypes.h"
#include "scriplib.h"
#include "gamedefs.h"
#include "keyboard.h"
#include "function.h"
#include "control.h"
#include "fx_man.h"
#include "sounds.h"
#include "config.h"
#include "common.h"
#include "common_game.h"

// we load this in to get default button and key assignments
// as well as setting up function mappings

#include "_functio.h"
#include "_config.h"

#include "renderlayer.h"

#if defined RENDERTYPESDL && defined SDL_TARGET && SDL_TARGET > 1
# include "sdl_inc.h"
#endif

extern void ReadGameSetup(int32_t scripthandle);
extern void WriteGameSetup(int32_t scripthandle);

ud_setup_t ud_setup{};
int g_noSetup;

//
// Comm variables
//

char CommPlayerName[32];
int32_t NumberPlayers,CommPort,PortSpeed,IrqNumber,UartAddress;

//
// Sound variables
//
int32_t FXToggle    = 1;
int32_t MusicToggle = 1;
int32_t FXDevice    = 0;
int32_t MusicDevice = ASS_AutoDetect;
int32_t NumVoices   = 32;
int32_t NumChannels = 2;
int32_t NumBits     = 16;
int32_t MixRate     = 44100;

uint8_t KeyboardKeys[NUMGAMEFUNCTIONS][2];
int32_t MouseButtons[MAXMOUSEBUTTONS];
int32_t MouseButtonsClicked[MAXMOUSEBUTTONS];
int32_t MouseAnalogScale[MAXMOUSEAXES];
int32_t JoystickButtons[MAXJOYBUTTONSANDHATS];
int32_t JoystickButtonsClicked[MAXJOYBUTTONSANDHATS];
int32_t JoystickDigitalAxes[MAXJOYAXES][2];
int32_t JoystickAnalogAxes[MAXJOYAXES];
int32_t JoystickAnalogDead[MAXJOYAXES];
int32_t JoystickAnalogSaturate[MAXJOYAXES];
int32_t JoystickAnalogScale[MAXJOYAXES];
float JoystickAnalogSensitivity[MAXJOYAXES];
int32_t JoystickAnalogInvert[MAXJOYAXES];

//
// Screen variables
//

extern char WangBangMacro[10][64];
char  RTSName[MAXRTSNAMELENGTH];
static int32_t scripthandle = -1;

// stubs to avoid clobbering the user's settings
#ifndef USE_OPENGL
static int32_t gltexfiltermode, glanisotropy, glusetexcompr;
#endif

/*
===================
=
= CONFIG_FunctionNameToNum
=
===================
*/

int32_t CONFIG_FunctionNameToNum(const char *func)
{
    int32_t i;

    if (!func) return -1;
    for (i=0; i<NUMGAMEFUNCTIONS; i++)
    {
        if (!Bstrcasecmp(func,gamefunctions[i]))
        {
            return i;
        }
    }
    return -1;
}

/*
===================
=
= CONFIG_FunctionNumToName
=
===================
*/

const char *CONFIG_FunctionNumToName(int32_t func)
{
    if ((unsigned)func >= (unsigned)NUMGAMEFUNCTIONS)
    {
        return NULL;
    }
    else
    {
        return gamefunctions[func];
    }
}

/*
===================
=
= CONFIG_AnalogNameToNum
=
===================
*/
int32_t CONFIG_AnalogNameToNum(const char *func)
{
    if (!Bstrcasecmp(func,"analog_turning"))
    {
        return analog_turning;
    }
    if (!Bstrcasecmp(func,"analog_strafing"))
    {
        return analog_strafing;
    }
    if (!Bstrcasecmp(func,"analog_moving"))
    {
        return analog_moving;
    }
    if (!Bstrcasecmp(func,"analog_lookingupanddown"))
    {
        return analog_lookingupanddown;
    }
    return -1;
}

const char *CONFIG_AnalogNumToName(int32_t func)
{
    switch (func)
    {
    case analog_turning:
        return "analog_turning";
    case analog_strafing:
        return "analog_strafing";
    case analog_moving:
        return "analog_moving";
    case analog_lookingupanddown:
        return "analog_lookingupanddown";
    default: break;
    }

    return NULL;
}

/*
===================
=
= CONFIG_SetDefaults
=
===================
*/

static void CONFIG_SetJoystickButtonFunction(int i, int j, int function)
{
    if (j)
        JoystickButtonsClicked[i] = function;
    else
        JoystickButtons[i] = function;

    CONTROL_MapButton(function, i, j, controldevice_joystick);
}

static void CONFIG_SetJoystickDigitalAxisFunction(int i, int j, int function)
{
    JoystickDigitalAxes[i][j] = function;
    CONTROL_MapDigitalAxis(i, function, j);
}

static void CONFIG_SetJoystickAnalogAxisFunction(int i, int function)
{
    JoystickAnalogAxes[i] = function;
    CONTROL_MapAnalogAxis(i, function);
}

struct GameControllerButtonSetting
{
    GameControllerButton button;
    int function;

    void apply() const
    {
        CONFIG_SetJoystickButtonFunction(button, 0, function);
    }
};
struct GameControllerAnalogAxisSetting
{
    GameControllerAxis axis;
    int function;

    void apply() const
    {
        CONFIG_SetJoystickAnalogAxisFunction(axis, function);
    }
};
struct GameControllerDigitalAxisSetting
{
    GameControllerAxis axis;
    int polarity;
    int function;

    void apply() const
    {
        CONFIG_SetJoystickDigitalAxisFunction(axis, polarity, function);
    }
};

static void CONFIG_SetJoystickAnalogAxisScale(int i, int32_t scale)
{
    JoystickAnalogScale[i] = scale;
    CONTROL_SetAnalogAxisScale(i, scale, controldevice_joystick);
}
static void CONFIG_SetJoystickAnalogAxisInvert(int i, int invert)
{
    JoystickAnalogInvert[i] = invert;
    CONTROL_SetAnalogAxisInvert(i, invert);
}
static void CONFIG_SetJoystickAnalogAxisDeadSaturate(int i, int dead, int saturate)
{
    JoystickAnalogDead[i] = dead;
    JoystickAnalogSaturate[i] = saturate;
    JOYSTICK_SetDeadZone(i, dead, saturate);
}

static void CONFIG_SetGameControllerAxesModern()
{
    static GameControllerAnalogAxisSetting const analogAxes[] =
    {
        { CONTROLLER_AXIS_LEFTX, analog_strafing },
        { CONTROLLER_AXIS_LEFTY, analog_moving },
        { CONTROLLER_AXIS_RIGHTX, analog_turning },
        { CONTROLLER_AXIS_RIGHTY, analog_lookingupanddown },
    };

    CONFIG_SetJoystickAnalogAxisScale(CONTROLLER_AXIS_RIGHTX, DEFAULTAXISSCALE);
    CONFIG_SetJoystickAnalogAxisScale(CONTROLLER_AXIS_RIGHTY, DEFAULTAXISSCALE);

    for (auto const & analogAxis : analogAxes)
        analogAxis.apply();
}

void CONFIG_SetGameControllerDefaultsClear()
{
    for (int i=0; i<MAXJOYBUTTONSANDHATS; i++)
    {
        CONFIG_SetJoystickButtonFunction(i, 0, -1);
        CONFIG_SetJoystickButtonFunction(i, 1, -1);
    }

    for (int i=0; i<MAXJOYAXES; i++)
    {
        CONFIG_SetJoystickAnalogAxisScale(i, DEFAULTAXISSCALE);
        CONFIG_SetJoystickAnalogAxisInvert(i, 0);
        CONFIG_SetJoystickAnalogAxisDeadSaturate(i, DEFAULTAXISDEADZONE, DEFAULTAXISSATURATE);

        CONFIG_SetJoystickDigitalAxisFunction(i, 0, -1);
        CONFIG_SetJoystickDigitalAxisFunction(i, 1, -1);

        CONFIG_SetJoystickAnalogAxisFunction(i, -1);
    }
}

void SetGameControllerDefaults()
{
    CONFIG_SetGameControllerDefaultsClear();
    CONFIG_SetGameControllerAxesModern();

    static GameControllerButtonSetting const buttons[] =
    {
        { CONTROLLER_BUTTON_A, gamefunc_Open },
        { CONTROLLER_BUTTON_BACK, gamefunc_Map },
        { CONTROLLER_BUTTON_LEFTSTICK, gamefunc_Run },
        { CONTROLLER_BUTTON_RIGHTSTICK, gamefunc_Crouch },
        { CONTROLLER_BUTTON_DPAD_UP, gamefunc_Previous_Weapon },
        { CONTROLLER_BUTTON_DPAD_DOWN, gamefunc_Next_Weapon },
        { CONTROLLER_BUTTON_LEFTSHOULDER, gamefunc_Crouch },
        { CONTROLLER_BUTTON_RIGHTSHOULDER, gamefunc_Alt_Weapon_Mode },
    };

    static GameControllerButtonSetting const buttonsDuke[] =
    {
        { CONTROLLER_BUTTON_X, gamefunc_Inventory },
        { CONTROLLER_BUTTON_DPAD_LEFT, gamefunc_Inventory_Left },
        { CONTROLLER_BUTTON_DPAD_RIGHT, gamefunc_Inventory_Right },
    };

    static GameControllerDigitalAxisSetting const digitalAxes[] =
    {
        { CONTROLLER_AXIS_TRIGGERLEFT, 1, gamefunc_Jump },
        { CONTROLLER_AXIS_TRIGGERRIGHT, 1, gamefunc_Fire },
    };

    for (auto const & button : buttons)
        button.apply();

    for (auto const & button : buttonsDuke)
        button.apply();

    for (auto const & digitalAxis : digitalAxes)
        digitalAxis.apply();
}

void CONFIG_SetDefaults(void)
{
    // JBF 20031211
    int32_t i;

    ud_setup.ScreenMode = 1;

#if defined RENDERTYPESDL && SDL_MAJOR_VERSION > 1
    uint32_t inited = SDL_WasInit(SDL_INIT_VIDEO);
    if (inited == 0)
        SDL_Init(SDL_INIT_VIDEO);
    else if (!(inited & SDL_INIT_VIDEO))
        SDL_InitSubSystem(SDL_INIT_VIDEO);

    SDL_DisplayMode dm;
    if (SDL_GetDesktopDisplayMode(0, &dm) == 0)
    {
        ud_setup.ScreenWidth = dm.w;
        ud_setup.ScreenHeight = dm.h;
    }
    else
#endif
    {
        ud_setup.ScreenWidth = 1024;
        ud_setup.ScreenHeight = 768;
    }

    ud_setup.ScreenBPP = 32;
    FXToggle = 1;
    MusicToggle = 1;
    FXDevice = 0;
    MusicDevice = ASS_AutoDetect;
    NumVoices = 32;
    NumChannels = 2;
    NumBits = 16;
    MixRate = 44100;
    memcpy(&gs, &gs_defaults, sizeof(gs));

    Bstrcpy(RTSName, DEFAULTRTSFILE);
    Bstrcpy(CommPlayerName, DEFAULTPLAYERNAME);

    Bstrcpy(WangBangMacro[0], MACRO1);
    Bstrcpy(WangBangMacro[1], MACRO2);
    Bstrcpy(WangBangMacro[2], MACRO3);
    Bstrcpy(WangBangMacro[3], MACRO4);
    Bstrcpy(WangBangMacro[4], MACRO5);
    Bstrcpy(WangBangMacro[5], MACRO6);
    Bstrcpy(WangBangMacro[6], MACRO7);
    Bstrcpy(WangBangMacro[7], MACRO8);
    Bstrcpy(WangBangMacro[8], MACRO9);
    Bstrcpy(WangBangMacro[9], MACRO10);

    SetDefaultKeyDefinitions(1);
    SetMouseDefaults(1);
    SetGameControllerDefaults();
    gs.MouseAimingOn = TRUE;
    gs.AutoRun = TRUE;

    for (i=0; i<MAXMOUSEAXES; i++)
        MouseAnalogScale[i] = 65536;
    gs.MouseSpeed = DEFAULTMOUSESENSITIVITY*8192; // fix magic scale factor
    CONTROL_MouseSensitivity = DEFAULTMOUSESENSITIVITY;

}

void SetDefaultKeyDefinitions(int style)
{
    int numkeydefaults;
    const char **keydefaultset;
    int i, f, k1, k2;

    if (style)
    {
        numkeydefaults = sizeof(keydefaults_modern) / sizeof(char *) / 3;
        keydefaultset = keydefaults_modern;
    }
    else
    {
        numkeydefaults = sizeof(keydefaults) / sizeof(char *) / 3;
        keydefaultset = keydefaults;
    }

    memset(KeyboardKeys, 0xff, sizeof(KeyboardKeys));
    for (i=0; i < numkeydefaults; i++)
    {
        f = CONFIG_FunctionNameToNum(keydefaultset[3*i+0]);
        if (f == -1) continue;
        k1 = KB_StringToScanCode(keydefaultset[3*i+1]);
        k2 = KB_StringToScanCode(keydefaultset[3*i+2]);
        CONTROL_MapKey(i, k1, k2);

        KeyboardKeys[f][0] = k1;
        KeyboardKeys[f][1] = k2;
    }
}

void SetMouseDefaults(int style)
{
    int nummousedefaults;
    const char **mousedefaultset, **mouseclickeddefaultset;
    int i;

    if (style)
    {
        nummousedefaults = sizeof(mousedefaults_modern) / sizeof(char *);
        mousedefaultset = mousedefaults_modern;
        mouseclickeddefaultset = mouseclickeddefaults_modern;
    }
    else
    {
        nummousedefaults = sizeof(mousedefaults) / sizeof(char *);
        mousedefaultset = mousedefaults;
        mouseclickeddefaultset = mouseclickeddefaults;
    }

    memset(MouseButtons, -1, sizeof(MouseButtons));
    memset(MouseButtonsClicked, -1, sizeof(MouseButtonsClicked));
    for (i=0; i < nummousedefaults; i++)
    {
        MouseButtons[i] = CONFIG_FunctionNameToNum(mousedefaultset[i]);
        CONTROL_MapButton(MouseButtons[i], i, FALSE, controldevice_mouse);

        if (i<4) continue;

        MouseButtonsClicked[i] = CONFIG_FunctionNameToNum(mouseclickeddefaultset[i]);
        CONTROL_MapButton(MouseButtonsClicked[i], i, TRUE,  controldevice_mouse);
    }
}

/*
===================
=
= CONFIG_ReadKeys
=
===================
*/

void CONFIG_ReadKeys(int32_t scripthandle)
{
    int32_t i;
    int32_t numkeyentries;
    int32_t function;
    char keyname1[80];
    char keyname2[80];
    kb_scancode key1,key2;

    if (scripthandle < 0) return;

    numkeyentries = SCRIPT_NumberEntries(scripthandle,"KeyDefinitions");

    for (i=0; i<numkeyentries; i++)
    {
        function = CONFIG_FunctionNameToNum(SCRIPT_Entry(scripthandle,"KeyDefinitions", i));
        if (function != -1)
        {
            memset(keyname1,0,sizeof(keyname1));
            memset(keyname2,0,sizeof(keyname2));
            SCRIPT_GetDoubleString
            (
                scripthandle,
                "KeyDefinitions",
                SCRIPT_Entry(scripthandle, "KeyDefinitions", i),
                keyname1,
                keyname2
            );
            key1 = 0xff;
            key2 = 0xff;
            if (keyname1[0])
            {
                key1 = (uint8_t) KB_StringToScanCode(keyname1);
            }
            if (keyname2[0])
            {
                key2 = (uint8_t) KB_StringToScanCode(keyname2);
            }
            KeyboardKeys[function][0] = key1;
            KeyboardKeys[function][1] = key2;
        }
    }

    for (i=0; i<NUMGAMEFUNCTIONS; i++)
    {
        if (i == gamefunc_Show_Console)
            OSD_CaptureKey(KeyboardKeys[i][0]);
        else
            CONTROL_MapKey(i, KeyboardKeys[i][0], KeyboardKeys[i][1]);
    }
}

/*
===================
=
= CONFIG_SetupMouse
=
===================
*/

void CONFIG_SetupMouse(void)
{
    int32_t i;
    char str[80];
    char temp[80];
    int32_t function, scale;

    if (scripthandle < 0) return;

    for (i=0; i<MAXMOUSEBUTTONS; i++)
    {
        Bsprintf(str,"MouseButton%d",i); temp[0] = 0;
        if (!SCRIPT_GetString(scripthandle,"Controls", str,temp))
            MouseButtons[i] = CONFIG_FunctionNameToNum(temp);

        Bsprintf(str,"MouseButtonClicked%d",i); temp[0] = 0;
        if (!SCRIPT_GetString(scripthandle,"Controls", str,temp))
            MouseButtonsClicked[i] = CONFIG_FunctionNameToNum(temp);
    }

    // map over the axes
    for (i=0; i<MAXMOUSEAXES; i++)
    {
        Bsprintf(str,"MouseAnalogScale%d",i);
        scale = MouseAnalogScale[i];
        SCRIPT_GetNumber(scripthandle, "Controls", str,&scale);
        MouseAnalogScale[i] = scale;
    }

    // 0 to 65536
    SCRIPT_GetNumber(scripthandle, "Controls","MouseSensitivity",&function);
    gs.MouseSpeed = function;

    for (i=0; i<MAXMOUSEBUTTONS; i++)
    {
        CONTROL_MapButton(MouseButtons[i], i, FALSE, controldevice_mouse);
        CONTROL_MapButton(MouseButtonsClicked[i], i, TRUE,  controldevice_mouse);
    }
    for (i=0; i<MAXMOUSEAXES; i++)
    {
        CONTROL_SetAnalogAxisSensitivity(i, MouseAnalogScale[i] * (1.f/2560.f), controldevice_mouse);
    }

    CONTROL_MouseSensitivity = float(gs.MouseSpeed) * (1.f/8192.f); // fix magic scale factor
}

/*
===================
=
= CONFIG_SetupJoystick
=
===================
*/

void CONFIG_SetupJoystick(void)
{
    int32_t i;
    char str[80];
    char temp[80];
    int32_t scale;

    if (scripthandle < 0) return;

    for (i=0; i<MAXJOYBUTTONS; i++)
    {
        Bsprintf(str,"JoystickButton%d",i); temp[0] = 0;
        if (!SCRIPT_GetString(scripthandle,"Controls", str,temp))
            JoystickButtons[i] = CONFIG_FunctionNameToNum(temp);

        Bsprintf(str,"JoystickButtonClicked%d",i); temp[0] = 0;
        if (!SCRIPT_GetString(scripthandle,"Controls", str,temp))
            JoystickButtonsClicked[i] = CONFIG_FunctionNameToNum(temp);
    }

    // map over the axes
    for (i=0; i<MAXJOYAXES; i++)
    {
        Bsprintf(str,"JoystickAnalogAxes%d",i); temp[0] = 0;
        if (!SCRIPT_GetString(scripthandle, "Controls", str,temp))
            JoystickAnalogAxes[i] = CONFIG_AnalogNameToNum(temp);

        Bsprintf(str,"JoystickDigitalAxes%d_0",i); temp[0] = 0;
        if (!SCRIPT_GetString(scripthandle, "Controls", str,temp))
            JoystickDigitalAxes[i][0] = CONFIG_FunctionNameToNum(temp);

        Bsprintf(str,"JoystickDigitalAxes%d_1",i); temp[0] = 0;
        if (!SCRIPT_GetString(scripthandle, "Controls", str,temp))
            JoystickDigitalAxes[i][1] = CONFIG_FunctionNameToNum(temp);

        Bsprintf(str,"JoystickAnalogScale%d",i);
        scale = JoystickAnalogScale[i];
        SCRIPT_GetNumber(scripthandle, "Controls", str,&scale);
        JoystickAnalogScale[i] = scale;

        Bsprintf(str,"JoystickAnalogDead%d",i);
        scale = JoystickAnalogDead[i];
        SCRIPT_GetNumber(scripthandle, "Controls", str,&scale);
        JoystickAnalogDead[i] = scale;

        Bsprintf(str,"JoystickAnalogSaturate%d",i);
        scale = JoystickAnalogSaturate[i];
        SCRIPT_GetNumber(scripthandle, "Controls", str,&scale);
        JoystickAnalogSaturate[i] = scale;
    }

    for (i=0; i<MAXJOYBUTTONS; i++)
    {
        CONTROL_MapButton(JoystickButtons[i], i, FALSE, controldevice_joystick);
        CONTROL_MapButton(JoystickButtonsClicked[i], i, TRUE,  controldevice_joystick);
    }
    for (i=0; i<MAXJOYAXES; i++)
    {
        CONTROL_MapAnalogAxis(i, JoystickAnalogAxes[i]);
        CONTROL_MapDigitalAxis(i, JoystickDigitalAxes[i][0], 0);
        CONTROL_MapDigitalAxis(i, JoystickDigitalAxes[i][1], 1);
        CONTROL_SetAnalogAxisScale(i, JoystickAnalogScale[i], controldevice_joystick);
        //CONTROL_SetJoyAxisDead(i, JoystickAnalogDead[i]);
        //CONTROL_SetJoyAxisSaturate(i, JoystickAnalogSaturate[i]);
        JOYSTICK_SetDeadZone(i, JoystickAnalogDead[i], JoystickAnalogSaturate[i]); // [JM] !CHECKME!
    }
}

/*
===================
=
= CONFIG_ReadSetup
=
===================
*/

int32_t CONFIG_ReadSetup(void)
{
    int32_t dummy;
    extern char PlayerNameArg[32];

    char waveformtrackname[MAXWAVEFORMTRACKLENGTH] = {0};

    CONTROL_ClearAssignments();
    CONFIG_SetDefaults();

    if (buildvfs_exists(setupfilename))
        scripthandle = SCRIPT_Load(setupfilename);

    if (scripthandle < 0) return -1;

    SCRIPT_GetNumber(scripthandle, "Screen Setup", "ScreenMode",&ud_setup.ScreenMode);
    SCRIPT_GetNumber(scripthandle, "Screen Setup", "ScreenWidth",&ud_setup.ScreenWidth);
    SCRIPT_GetNumber(scripthandle, "Screen Setup", "ScreenHeight",&ud_setup.ScreenHeight);
    SCRIPT_GetNumber(scripthandle, "Screen Setup", "ScreenBPP", &ud_setup.ScreenBPP);
    if (ud_setup.ScreenBPP < 8) ud_setup.ScreenBPP = 8;

    SCRIPT_GetNumber(scripthandle, "Screen Setup", "MaxRefreshFreq", (int32_t *)&maxrefreshfreq);

    SCRIPT_GetNumber(scripthandle, "Screen Setup", "GLTextureMode", &gltexfiltermode);
    SCRIPT_GetNumber(scripthandle, "Screen Setup", "GLAnisotropy", &glanisotropy);
    SCRIPT_GetNumber(scripthandle, "Screen Setup", "GLUseTextureCompr", &glusetexcompr);

    SCRIPT_GetNumber(scripthandle, "Sound Setup", "FXToggle",&FXToggle);
    SCRIPT_GetNumber(scripthandle, "Sound Setup", "MusicToggle",&MusicToggle);
    SCRIPT_GetNumber(scripthandle, "Sound Setup", "FXDevice",&FXDevice);
    SCRIPT_GetNumber(scripthandle, "Sound Setup", "MusicDevice",&MusicDevice);
    SCRIPT_GetNumber(scripthandle, "Sound Setup", "FXVolume",&dummy);
    gs.SoundVolume = dummy;
    SCRIPT_GetNumber(scripthandle, "Sound Setup", "MusicVolume",&dummy);
    gs.MusicVolume = dummy;

    SCRIPT_GetNumber(scripthandle, "Sound Setup", "NumVoices",&NumVoices);
    SCRIPT_GetNumber(scripthandle, "Sound Setup", "NumChannels",&NumChannels);
    SCRIPT_GetNumber(scripthandle, "Sound Setup", "NumBits",&NumBits);
    SCRIPT_GetNumber(scripthandle, "Sound Setup", "MixRate",&MixRate);
    SCRIPT_GetNumber(scripthandle, "Sound Setup", "ReverseStereo",&dummy);
    gs.FlipStereo = dummy;
    if (gs.FlipStereo) gs.FlipStereo = 1;

    SCRIPT_GetString(scripthandle, "Sound Setup", "WaveformTrackName", waveformtrackname);
    if (waveformtrackname[0] != '\0')
        memcpy(gs.WaveformTrackName, waveformtrackname, MAXWAVEFORMTRACKLENGTH);

    SCRIPT_GetNumber(scripthandle, "Setup", "ForceSetup",&ud_setup.ForceSetup);

    if (g_grpNamePtr == NULL && g_addonNum == -1)
    {
        SCRIPT_GetStringPtr(scripthandle, "Setup", "SelectedGRP", &g_grpNamePtr);
        if (g_grpNamePtr && !strlen(g_grpNamePtr))
            g_grpNamePtr = dup_filename(G_DefaultGrpFile());
    }

    SCRIPT_GetNumber(scripthandle, "Controls","UseMouse",&ud_setup.UseMouse);
    SCRIPT_GetNumber(scripthandle, "Controls","UseJoystick",&ud_setup.UseJoystick);
    SCRIPT_GetString(scripthandle, "Comm Setup", "RTSName",RTSName);

    SCRIPT_GetString(scripthandle, "Comm Setup","PlayerName",CommPlayerName);

    ReadGameSetup(scripthandle);

    CONFIG_ReadKeys(scripthandle);

    //CONFIG_SetupMouse(scripthandle);
    //CONFIG_SetupJoystick(scripthandle);

    if (PlayerNameArg[0] != '\0')
    {
        strcpy(CommPlayerName, PlayerNameArg);
    }
    return 0;
}

static void CONFIG_WriteCvars()
{
    static const char filename[] = "voidsw_cvars.cfg";

    buildvfs_FILE fp = buildvfs_fopen_write(filename);

    if (!fp)
    {
        OSD_Printf("Error writing %s: %s\n", filename, strerror(errno));
        return;
    }

    buildvfs_fputstr(fp, "// this file is automatically generated by ");
    buildvfs_fputstrptr(fp, AppProperName);
    buildvfs_fputstr(fp, "\n");

    OSD_WriteAliases(fp);
    OSD_WriteCvars(fp);

    buildvfs_fclose(fp);

    OSD_Printf("Wrote %s\n", filename);
}

/*
===================
=
= CONFIG_WriteSetup
=
===================
*/

void CONFIG_WriteSetup(void)
{
    int32_t dummy;
    char buf[80];

    if (scripthandle < 0)
        scripthandle = SCRIPT_Init(setupfilename);

    SCRIPT_PutNumber(scripthandle, "Screen Setup", "ScreenWidth", ud_setup.ScreenWidth,FALSE,FALSE);
    SCRIPT_PutNumber(scripthandle, "Screen Setup", "ScreenHeight",ud_setup.ScreenHeight,FALSE,FALSE);
    SCRIPT_PutNumber(scripthandle, "Screen Setup", "ScreenMode",ud_setup.ScreenMode,FALSE,FALSE);
    SCRIPT_PutNumber(scripthandle, "Screen Setup", "ScreenBPP",ud_setup.ScreenBPP,FALSE,FALSE);
    SCRIPT_PutNumber(scripthandle, "Screen Setup", "MaxRefreshFreq",maxrefreshfreq,FALSE,FALSE);

    SCRIPT_PutNumber(scripthandle, "Screen Setup", "GLTextureMode",gltexfiltermode,FALSE,FALSE);
    SCRIPT_PutNumber(scripthandle, "Screen Setup", "GLAnisotropy",glanisotropy,FALSE,FALSE);
    SCRIPT_PutNumber(scripthandle, "Screen Setup", "GLUseTextureCompr",glusetexcompr,FALSE,FALSE);

    SCRIPT_PutNumber(scripthandle, "Sound Setup", "FXToggle", FXToggle, FALSE, FALSE);
    SCRIPT_PutNumber(scripthandle, "Sound Setup", "MusicToggle", MusicToggle, FALSE, FALSE);
    SCRIPT_PutNumber(scripthandle, "Sound Setup", "FXDevice", FXDevice, FALSE, FALSE);
    SCRIPT_PutNumber(scripthandle, "Sound Setup", "MusicDevice", MusicDevice, FALSE, FALSE);
    SCRIPT_PutNumber(scripthandle, "Sound Setup", "NumVoices", NumVoices, FALSE, FALSE);
    SCRIPT_PutNumber(scripthandle, "Sound Setup", "NumChannels", NumChannels, FALSE, FALSE);
    SCRIPT_PutNumber(scripthandle, "Sound Setup", "NumBits", NumBits, FALSE, FALSE);
    SCRIPT_PutNumber(scripthandle, "Sound Setup", "MixRate", MixRate, FALSE, FALSE);
    SCRIPT_PutNumber(scripthandle, "Sound Setup", "FXVolume",gs.SoundVolume,FALSE,FALSE);
    SCRIPT_PutNumber(scripthandle, "Sound Setup", "MusicVolume",gs.MusicVolume,FALSE,FALSE);
    dummy = gs.FlipStereo;
    SCRIPT_PutNumber(scripthandle, "Sound Setup", "ReverseStereo",dummy,FALSE,FALSE);
    SCRIPT_PutString(scripthandle, "Sound Setup", "WaveformTrackName", gs.WaveformTrackName);

    SCRIPT_PutNumber(scripthandle, "Setup", "ForceSetup",ud_setup.ForceSetup,FALSE,FALSE);

    if (g_grpNamePtr && g_addonNum == -1)
        SCRIPT_PutString(scripthandle, "Setup", "SelectedGRP", g_grpNamePtr);

    SCRIPT_PutNumber(scripthandle, "Controls","UseMouse",ud_setup.UseMouse,FALSE,FALSE);
    SCRIPT_PutNumber(scripthandle, "Controls","UseJoystick",ud_setup.UseJoystick,FALSE,FALSE);
    SCRIPT_PutNumber(scripthandle, "Controls","MouseSensitivity",gs.MouseSpeed,FALSE,FALSE);

    WriteGameSetup(scripthandle);

    for (dummy=0; dummy<NUMGAMEFUNCTIONS; dummy++)
    {
        SCRIPT_PutDoubleString(scripthandle, "KeyDefinitions", CONFIG_FunctionNumToName(dummy),
                               KB_ScanCodeToString(KeyboardKeys[dummy][0]), KB_ScanCodeToString(KeyboardKeys[dummy][1]));
    }

    for (dummy=0; dummy<MAXMOUSEBUTTONS; dummy++)
    {
        Bsprintf(buf,"MouseButton%d",dummy);
        SCRIPT_PutString(scripthandle,"Controls", buf, CONFIG_FunctionNumToName(MouseButtons[dummy]));

        if (dummy >= (MAXMOUSEBUTTONS-2)) continue; // scroll wheel

        Bsprintf(buf,"MouseButtonClicked%d",dummy);
        SCRIPT_PutString(scripthandle,"Controls", buf, CONFIG_FunctionNumToName(MouseButtonsClicked[dummy]));
    }

    for (dummy=0; dummy<MAXMOUSEAXES; dummy++)
    {
        Bsprintf(buf,"MouseAnalogScale%d",dummy);
        SCRIPT_PutNumber(scripthandle, "Controls", buf, MouseAnalogScale[dummy], FALSE, FALSE);
    }

    for (dummy=0; dummy<MAXJOYBUTTONS; dummy++)
    {
        Bsprintf(buf,"JoystickButton%d",dummy);
        SCRIPT_PutString(scripthandle,"Controls", buf, CONFIG_FunctionNumToName(JoystickButtons[dummy]));

        Bsprintf(buf,"JoystickButtonClicked%d",dummy);
        SCRIPT_PutString(scripthandle,"Controls", buf, CONFIG_FunctionNumToName(JoystickButtonsClicked[dummy]));
    }

    for (dummy=0; dummy<MAXJOYAXES; dummy++)
    {
        Bsprintf(buf,"JoystickAnalogAxes%d",dummy);
        SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_AnalogNumToName(JoystickAnalogAxes[dummy]));

        Bsprintf(buf,"JoystickDigitalAxes%d_0",dummy);
        SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_FunctionNumToName(JoystickDigitalAxes[dummy][0]));

        Bsprintf(buf,"JoystickDigitalAxes%d_1",dummy);
        SCRIPT_PutString(scripthandle, "Controls", buf, CONFIG_FunctionNumToName(JoystickDigitalAxes[dummy][1]));

        Bsprintf(buf,"JoystickAnalogScale%d",dummy);
        SCRIPT_PutNumber(scripthandle, "Controls", buf, JoystickAnalogScale[dummy], FALSE, FALSE);

        Bsprintf(buf,"JoystickAnalogDead%d",dummy);
        SCRIPT_PutNumber(scripthandle, "Controls", buf, JoystickAnalogDead[dummy], FALSE, FALSE);

        Bsprintf(buf,"JoystickAnalogSaturate%d",dummy);
        SCRIPT_PutNumber(scripthandle, "Controls", buf, JoystickAnalogSaturate[dummy], FALSE, FALSE);
    }

    SCRIPT_Save(scripthandle, setupfilename);
    SCRIPT_Free(scripthandle);

    CONFIG_WriteCvars();
}


code:
//-------------------------------------------------------------------------
/*
Copyright (C) 1997, 2005 - 3D Realms Entertainment

This file is part of Shadow Warrior version 1.2

Shadow Warrior 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.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

Original Source: 1997 - Frank Maddin and Jim Norwood
Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
*/
//-------------------------------------------------------------------------

#ifndef config_public_
#define config_public_

#include "compat.h"

#include "function.h"
#include "keyboard.h"
#include "control.h"

#ifdef __cplusplus
struct ud_setup_t {
    union {
      int32_t usejoystick, UseJoystick = {0};
    };
    union {
      int32_t usemouse, UseMouse = {1};
    };
    union {
      int32_t fullscreen, ScreenMode = {1};
    };
    union {
      int32_t xdim, ScreenWidth = {640};
    };
    union {
      int32_t ydim, ScreenHeight = {480};
    };
    union {
      int32_t bpp, ScreenBPP = {32};
    };
    union {
      int32_t forcesetup, ForceSetup = {1};
    };
    int32_t noautoload = 0;
};

extern "C" {

extern ud_setup_t ud_setup;
#endif

extern int g_noSetup;

#define SETUPNAMEPARM "SETUPFILE"

// screen externs
extern int32_t ScreenBufferMode;
extern int32_t VesaBufferMode;

// sound externs
extern int32_t FXToggle;
extern int32_t MusicToggle;
extern int32_t FXDevice; // Sound FX Card number
extern int32_t MusicDevice; // Music Card number
extern int32_t FXVolume; // FX Volume
extern int32_t MusicVolume; // Music Volume
extern int32_t NumVoices; // Number of voices
extern int32_t NumChannels; // Number of channels
extern int32_t NumBits; // Number of bits
extern int32_t MixRate; // Mixing rate
extern int32_t MidiPort; // Midi Port
extern int32_t ReverseStereo; // Reverse Stereo Channels

// comm externs
extern int32_t ComPort;
extern int32_t IrqNumber;
extern int32_t UartAddress;
extern int32_t PortSpeed;

extern int32_t ToneDial;
extern char  ModemName[MAXMODEMSTRING];
extern char  InitString[MAXMODEMSTRING];
extern char  HangupString[MAXMODEMSTRING];
extern char  DialoutString[MAXMODEMSTRING];
extern int32_t SocketNumber;
extern char  CommbatMacro[MAXMACROS][MAXMACROLENGTH];
extern char  PhoneNames[MAXPHONEENTRIES][PHONENAMELENGTH];
extern char  PhoneNumbers[MAXPHONEENTRIES][PHONENUMBERLENGTH];
extern char  PhoneNumber[PHONENUMBERLENGTH];
extern int32_t NumberPlayers;
extern int32_t ConnectType;
extern char  PlayerName[MAXPLAYERNAMELENGTH];
extern char  RTSName[MAXRTSNAMELENGTH];
extern char  UserLevel[MAXUSERLEVELNAMELENGTH];
extern char  RTSPath[MAXRTSPATHLENGTH];
extern char  UserPath[MAXUSERLEVELPATHLENGTH];

// controller externs
extern int32_t JoystickPort;
extern int32_t MouseSensitivity;
extern int32_t MouseAiming;
extern int32_t MouseAimingFlipped;

extern uint8_t KeyboardKeys[NUMGAMEFUNCTIONS][2];

extern int32_t MouseButtons[MAXMOUSEBUTTONS];
extern int32_t MouseButtonsClicked[MAXMOUSEBUTTONS];

extern int32_t JoystickButtons[MAXJOYBUTTONSANDHATS];
extern int32_t JoystickButtonsClicked[MAXJOYBUTTONSANDHATS];

extern int32_t JoystickAnalogAxes[MAXJOYAXES];
extern int32_t MouseAnalogScale[MAXMOUSEAXES];
extern int32_t JoystickAnalogScale[MAXJOYAXES];
extern int32_t JoystickAnalogDead[MAXJOYAXES];
extern int32_t JoystickAnalogSaturate[MAXJOYAXES];

extern int32_t EnableRudder;

extern int32_t JoystickDigitalAxes[MAXJOYAXES][2];

extern char setupfilename[BMAX_PATH];
extern char ExternalControlFilename[64];

//style=0: classic
//style=1: modern
void SetMouseDefaults(int style);
void SetJoystickDefaults(void);
void SetDefaultKeyDefinitions(int style);

int32_t CONFIG_ReadSetup(void);
void CONFIG_SetupMouse(void);
void CONFIG_SetupJoystick(void);
void CONFIG_WriteSetup(void);
void WriteCommitFile(int32_t gametype);
void CONFIG_GetSetupFilename(void);

const char *CONFIG_FunctionNumToName(int32_t func);
int32_t CONFIG_FunctionNameToNum(const char *func);
const char *CONFIG_AnalogNumToName(int32_t func);
int32_t CONFIG_AnalogNameToNum(const char *func);

#ifdef __cplusplus
};
#endif
#endif


code:
//-------------------------------------------------------------------------
/*
Copyright (C) 1997, 2005 - 3D Realms Entertainment

This file is part of Shadow Warrior version 1.2

Shadow Warrior 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.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

Original Source: 1997 - Frank Maddin and Jim Norwood
Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
*/
//-------------------------------------------------------------------------

#include "names.h"
#include "names2.h"
//#include "panel.h"

#ifdef MAKE_CONPIC_ENUM
#define CONPIC_ENTRY(tile,name) ID_ ## name = tile,
#endif

////////////////////////////////////////////////////////////////////////////////
//
// SWORD
//
////////////////////////////////////////////////////////////////////////////////

#define SWORD_REST 2080
#define SWORD_SWING0 2081
#define SWORD_SWING1 2082
#define SWORD_SWING2 2083

CONPIC_ENTRY(SWORD_REST+0,SwordPresent0)

CONPIC_ENTRY(SWORD_SWING0,SwordSwing0)
CONPIC_ENTRY(SWORD_SWING1,SwordSwing1)
CONPIC_ENTRY(SWORD_SWING2,SwordSwing2)

CONPIC_ENTRY(SWORD_SWING0,SwordSwingR0)
CONPIC_ENTRY(SWORD_SWING1,SwordSwingR1)
CONPIC_ENTRY(SWORD_SWING2,SwordSwingR2)

#define BLOODYSWORD_REST 4090
#define BLOODYSWORD_SWING0 4091
#define BLOODYSWORD_SWING1 4092
#define BLOODYSWORD_SWING2 4093

CONPIC_ENTRY(BLOODYSWORD_REST,BloodySwordPresent0)

CONPIC_ENTRY(BLOODYSWORD_SWING0,BloodySwordSwing0)
CONPIC_ENTRY(BLOODYSWORD_SWING1,BloodySwordSwing1)
CONPIC_ENTRY(BLOODYSWORD_SWING2,BloodySwordSwing2)

CONPIC_ENTRY(BLOODYSWORD_SWING0,BloodySwordSwingR0)
CONPIC_ENTRY(BLOODYSWORD_SWING1,BloodySwordSwingR1)
CONPIC_ENTRY(BLOODYSWORD_SWING2,BloodySwordSwingR2)

////////////////////////////////////////////////////////////////////////////////
//
// FIST
//
////////////////////////////////////////////////////////////////////////////////

#define FIST_REST 4070
#define FIST_SWING0 4071
#define FIST_SWING1 4072
#define FIST_SWING2 4073

CONPIC_ENTRY(FIST_REST+0,FistPresent0)

CONPIC_ENTRY(FIST_SWING0,FistSwing0)
CONPIC_ENTRY(FIST_SWING1,FistSwing1)
CONPIC_ENTRY(FIST_SWING2,FistSwing2)

#define BLOODYFIST_REST 4074
#define BLOODYFIST_SWING0 4075
#define BLOODYFIST_SWING1 4076
#define BLOODYFIST_SWING2 4077

#define FIST2_REST 4050
#define FIST2_SWING0 4051
#define FIST2_SWING1 4052
#define FIST2_SWING2 4053

CONPIC_ENTRY(FIST2_REST+0,Fist2Present0)

CONPIC_ENTRY(FIST2_SWING0,Fist2Swing0)
CONPIC_ENTRY(FIST2_SWING1,Fist2Swing1)
CONPIC_ENTRY(FIST2_SWING2,Fist2Swing2)

#define BLOODYFIST2_REST 4054
#define BLOODYFIST2_SWING0 4055
#define BLOODYFIST2_SWING1 4056
#define BLOODYFIST2_SWING2 4057

#define FIST3_REST 4060
#define FIST3_SWING0 4061
#define FIST3_SWING1 4062
#define FIST3_SWING2 4063

CONPIC_ENTRY(FIST3_REST+0,Fist3Present0)

CONPIC_ENTRY(FIST3_SWING0,Fist3Swing0)
CONPIC_ENTRY(FIST3_SWING1,Fist3Swing1)
CONPIC_ENTRY(FIST3_SWING2,Fist3Swing2)

#define BLOODYFIST3_REST 4064
#define BLOODYFIST3_SWING0 4065
#define BLOODYFIST3_SWING1 4066
#define BLOODYFIST3_SWING2 4067

////////////////////////////////////////////////////////////////////////////////
//
// KICK
//
////////////////////////////////////////////////////////////////////////////////

#define KICK0 4080
#define KICK1 4081

CONPIC_ENTRY(KICK0,Kick0)
CONPIC_ENTRY(KICK1,Kick1)

#define BLOODYKICK0 4082
#define BLOODYKICK1 4083

///////////////////////////////////////////////////////////////////////////////
//
// SHRUIKEN
//
///////////////////////////////////////////////////////////////////////////////

#define STAR_REST 2130
#define STAR_THROW 2133

CONPIC_ENTRY(STAR_REST+0,StarPresent0)

CONPIC_ENTRY(STAR_REST+1,StarDown0)
CONPIC_ENTRY(STAR_REST+2,StarDown1)

CONPIC_ENTRY(STAR_THROW+0,ThrowStar0)
CONPIC_ENTRY(STAR_THROW+1,ThrowStar1)
CONPIC_ENTRY(STAR_THROW+2,ThrowStar2)
CONPIC_ENTRY(STAR_THROW+3,ThrowStar3)
CONPIC_ENTRY(STAR_THROW+4,ThrowStar4)

///////////////////////////////////////////////////////////////////////////////////////
//
// UZI
//
///////////////////////////////////////////////////////////////////////////////////////

#if 0
#define UZI_REST 2000
#define UZI_FIRE_0 2001
#define UZI_FIRE_1 2001
#define UZI_EJECT 2003
#define UZI_CLIP 2005
#define UZI_RELOAD 2007
#else
// silencer
#define UZI_REST 2004
#define UZI_FIRE_0 2006
#define UZI_FIRE_1 2008
#define UZI_EJECT 2009
#define UZI_CLIP 2005
#define UZI_RELOAD 2007
#endif

#define UZI_SHELL 2152

// RIGHT UZI
CONPIC_ENTRY(UZI_REST,UziPresent0)

CONPIC_ENTRY(UZI_FIRE_0,UziFire0)
CONPIC_ENTRY(UZI_FIRE_1,UziFire1)

// LEFT UZI
CONPIC_ENTRY(UZI_REST,Uzi2Present0)

CONPIC_ENTRY(UZI_FIRE_0,Uzi2Fire0)
CONPIC_ENTRY(UZI_FIRE_1,Uzi2Fire1)
//eject
CONPIC_ENTRY(UZI_EJECT,UziEject0)

//clip
CONPIC_ENTRY(UZI_CLIP,UziClip0)

//reload
CONPIC_ENTRY(UZI_RELOAD,UziReload0)

CONPIC_ENTRY(UZI_SHELL+0,UziShell0)
CONPIC_ENTRY(UZI_SHELL+1,UziShell1)
CONPIC_ENTRY(UZI_SHELL+2,UziShell2)
CONPIC_ENTRY(UZI_SHELL+3,UziShell3)
CONPIC_ENTRY(UZI_SHELL+4,UziShell4)
CONPIC_ENTRY(UZI_SHELL+5,UziShell5)

CONPIC_ENTRY(UZI_SHELL+0,Uzi2Shell0)
CONPIC_ENTRY(UZI_SHELL+1,Uzi2Shell1)
CONPIC_ENTRY(UZI_SHELL+2,Uzi2Shell2)
CONPIC_ENTRY(UZI_SHELL+3,Uzi2Shell3)
CONPIC_ENTRY(UZI_SHELL+4,Uzi2Shell4)
CONPIC_ENTRY(UZI_SHELL+5,Uzi2Shell5)

////////////////////////////////////////////////////////////////////////////////
//
// SHOTGUN
//
////////////////////////////////////////////////////////////////////////////////

#define SHOTGUN_REST 2213
#define SHOTGUN_FIRE 2214
#define SHOTGUN_RELOAD0 2216
#define SHOTGUN_RELOAD1 2211
#define SHOTGUN_RELOAD2 2212

CONPIC_ENTRY(SHOTGUN_REST,ShotgunPresent0)

CONPIC_ENTRY(SHOTGUN_REST,ShotgunRest0)

CONPIC_ENTRY(SHOTGUN_RELOAD0,ShotgunReload0)
CONPIC_ENTRY(SHOTGUN_RELOAD1,ShotgunReload1)
CONPIC_ENTRY(SHOTGUN_RELOAD2,ShotgunReload2)

CONPIC_ENTRY(SHOTGUN_FIRE+0,ShotgunFire0)
CONPIC_ENTRY(SHOTGUN_FIRE+1,ShotgunFire1)

#define SHOTGUN_SHELL 2180
CONPIC_ENTRY(SHOTGUN_SHELL+0,ShotgunShell0)
CONPIC_ENTRY(SHOTGUN_SHELL+1,ShotgunShell1)
CONPIC_ENTRY(SHOTGUN_SHELL+2,ShotgunShell2)
CONPIC_ENTRY(SHOTGUN_SHELL+3,ShotgunShell3)
CONPIC_ENTRY(SHOTGUN_SHELL+4,ShotgunShell4)
CONPIC_ENTRY(SHOTGUN_SHELL+5,ShotgunShell5)
CONPIC_ENTRY(SHOTGUN_SHELL+6,ShotgunShell6)
CONPIC_ENTRY(SHOTGUN_SHELL+7,ShotgunShell7)

////////////////////////////////////////////////////////////////////////////////
//
// ROCKET
//
////////////////////////////////////////////////////////////////////////////////

#define ROCKET_REST 2211
#define ROCKET_FIRE 2212

CONPIC_ENTRY(ROCKET_REST+0,RocketPresent0)
CONPIC_ENTRY(ROCKET_REST+0,RocketRest0)

CONPIC_ENTRY(ROCKET_FIRE+0,RocketFire0)
CONPIC_ENTRY(ROCKET_FIRE+1,RocketFire1)
CONPIC_ENTRY(ROCKET_FIRE+2,RocketFire2)
CONPIC_ENTRY(ROCKET_FIRE+3,RocketFire3)
CONPIC_ENTRY(ROCKET_FIRE+4,RocketFire4)
CONPIC_ENTRY(ROCKET_FIRE+5,RocketFire5)

////////////////////////////////////////////////////////////////////////////////
//
// RAIL
//
////////////////////////////////////////////////////////////////////////////////

#define RAIL_REST 2010
#define RAIL_CHARGE 2015
#define RAIL_FIRE 2018

CONPIC_ENTRY(RAIL_REST+0,RailPresent0)

CONPIC_ENTRY(RAIL_REST+0,RailRest0)
CONPIC_ENTRY(RAIL_REST+1,RailRest1)
CONPIC_ENTRY(RAIL_REST+2,RailRest2)
CONPIC_ENTRY(RAIL_REST+3,RailRest3)
CONPIC_ENTRY(RAIL_REST+4,RailRest4)

CONPIC_ENTRY(RAIL_FIRE+0,RailFire0)
CONPIC_ENTRY(RAIL_FIRE+1,RailFire1)

CONPIC_ENTRY(RAIL_CHARGE+0,RailCharge0)
CONPIC_ENTRY(RAIL_CHARGE+1,RailCharge1)
CONPIC_ENTRY(RAIL_CHARGE+2,RailCharge2)

////////////////////////////////////////////////////////////////////////////////
//
// FIREBALL
//
////////////////////////////////////////////////////////////////////////////////

//#define HOTHEAD_REST 2327
//#define HOTHEAD_ATTACK 2327
#define HOTHEAD_REST 2048
#define HOTHEAD_ATTACK 2049
#define HOTHEAD_CENTER 2327
#define HOTHEAD_TURN 2314
#define HOTHEAD_CHOMP 2318

CONPIC_ENTRY(HOTHEAD_REST+0,HotheadPresent0)
CONPIC_ENTRY(HOTHEAD_REST+0,HotheadRest0)
CONPIC_ENTRY(HOTHEAD_ATTACK+0,HotheadAttack0)

CONPIC_ENTRY(HOTHEAD_CENTER+0,HotheadCenter0)

CONPIC_ENTRY(HOTHEAD_TURN+0,HotheadTurn0)
CONPIC_ENTRY(HOTHEAD_TURN+1,HotheadTurn1)
CONPIC_ENTRY(HOTHEAD_TURN+2,HotheadTurn2)
CONPIC_ENTRY(HOTHEAD_TURN+3,HotheadTurn3)

CONPIC_ENTRY(HOTHEAD_CHOMP+0,HotheadChomp0)

#define ON_FIRE 3157

CONPIC_ENTRY(ON_FIRE+0,OnFire0)
CONPIC_ENTRY(ON_FIRE+1,OnFire1)
CONPIC_ENTRY(ON_FIRE+2,OnFire2)
CONPIC_ENTRY(ON_FIRE+3,OnFire3)
CONPIC_ENTRY(ON_FIRE+4,OnFire4)
CONPIC_ENTRY(ON_FIRE+5,OnFire5)
CONPIC_ENTRY(ON_FIRE+6,OnFire6)
CONPIC_ENTRY(ON_FIRE+7,OnFire7)
CONPIC_ENTRY(ON_FIRE+8,OnFire8)
CONPIC_ENTRY(ON_FIRE+9,OnFire9)
CONPIC_ENTRY(ON_FIRE+10,OnFire10)
CONPIC_ENTRY(ON_FIRE+11,OnFire11)
CONPIC_ENTRY(ON_FIRE+12,OnFire12)

////////////////////////////////////////////////////////////////////////////////
//
// MICRO
//
////////////////////////////////////////////////////////////////////////////////

#define MICRO_REST 2070
#define MICRO_FIRE 2071
#define MICRO_SINGLE_FIRE 2071

CONPIC_ENTRY(MICRO_REST+0,MicroPresent0)

CONPIC_ENTRY(MICRO_FIRE+0,MicroFire0)
CONPIC_ENTRY(MICRO_FIRE+1,MicroFire1)
CONPIC_ENTRY(MICRO_FIRE+2,MicroFire2)
CONPIC_ENTRY(MICRO_FIRE+3,MicroFire3)

CONPIC_ENTRY(MICRO_SINGLE_FIRE+0,MicroSingleFire0)
CONPIC_ENTRY(MICRO_SINGLE_FIRE+1,MicroSingleFire1)
CONPIC_ENTRY(MICRO_SINGLE_FIRE+2,MicroSingleFire2)
CONPIC_ENTRY(MICRO_SINGLE_FIRE+3,MicroSingleFire3)

#if 0
////////////////////////////////////////////////////////////////////////////////
//
// NAPALM
//
////////////////////////////////////////////////////////////////////////////////

#define NAPALM_REST 2020
#define NAPALM_FIRE 2021

CONPIC_ENTRY(NAPALM_REST+0,NapalmPresent0)

CONPIC_ENTRY(NAPALM_FIRE+0,NapalmFire0)
CONPIC_ENTRY(NAPALM_FIRE+1,NapalmFire1)
CONPIC_ENTRY(NAPALM_FIRE+2,NapalmFire2)
CONPIC_ENTRY(NAPALM_FIRE+3,NapalmFire3)

////////////////////////////////////////////////////////////////////////////////
//
// RING
//
////////////////////////////////////////////////////////////////////////////////

#define RING_REST 2020
#define RING_FIRE 2021

CONPIC_ENTRY(RING_REST+0,RingPresent0)

CONPIC_ENTRY(RING_FIRE+0,RingFire0)
CONPIC_ENTRY(RING_FIRE+1,RingFire1)
CONPIC_ENTRY(RING_FIRE+2,RingFire2)
CONPIC_ENTRY(RING_FIRE+3,RingFire3)

////////////////////////////////////////////////////////////////////////////////
//
// ELECTRO
//
////////////////////////////////////////////////////////////////////////////////

#define ELECTRO_REST 2020
#define ELECTRO_FIRE 2021

CONPIC_ENTRY(ELECTRO_REST+0,ElectroPresent0)

CONPIC_ENTRY(ELECTRO_FIRE+0,ElectroFire0)
CONPIC_ENTRY(ELECTRO_FIRE+1,ElectroFire1)
CONPIC_ENTRY(ELECTRO_FIRE+2,ElectroFire2)
CONPIC_ENTRY(ELECTRO_FIRE+3,ElectroFire3)
#endif

////////////////////////////////////////////////////////////////////////////////
//
// GRENADE
//
////////////////////////////////////////////////////////////////////////////////

#define GRENADE_REST 2121
#define GRENADE_FIRE 2122
#define GRENADE_RELOAD 2125

CONPIC_ENTRY(GRENADE_REST+0,GrenadePresent0)

CONPIC_ENTRY(GRENADE_FIRE+0,GrenadeFire0)
CONPIC_ENTRY(GRENADE_FIRE+1,GrenadeFire1)
CONPIC_ENTRY(GRENADE_FIRE+2,GrenadeFire2)

CONPIC_ENTRY(GRENADE_RELOAD+0,GrenadeReload0)
CONPIC_ENTRY(GRENADE_RELOAD+1,GrenadeReload1)

////////////////////////////////////////////////////////////////////////////////
//
// MINE
//
////////////////////////////////////////////////////////////////////////////////

#define MINE_REST 2220
#define MINE_THROW 2222
#define MINE_RELOAD 2222

CONPIC_ENTRY(MINE_REST+0,MinePresent0)
CONPIC_ENTRY(MINE_REST+1,MinePresent1)

CONPIC_ENTRY(MINE_THROW+0,MineThrow0)

CONPIC_ENTRY(MINE_RELOAD+0,MineReload0)

////////////////////////////////////////////////////////////////////////////////
//
// HEART
//
////////////////////////////////////////////////////////////////////////////////

#define HEART_REST 2050

#define HEART_ATTACK 2052

CONPIC_ENTRY(HEART_REST+0,HeartPresent0)
CONPIC_ENTRY(HEART_REST+1,HeartPresent1)

CONPIC_ENTRY(HEART_ATTACK+0,HeartAttack0)
CONPIC_ENTRY(HEART_ATTACK+1,HeartAttack1)

//#define HEART_BLOOD 2430
#define HEART_BLOOD 2420
CONPIC_ENTRY(HEART_BLOOD+0,HeartBlood0)
CONPIC_ENTRY(HEART_BLOOD+1,HeartBlood1)
CONPIC_ENTRY(HEART_BLOOD+2,HeartBlood2)
CONPIC_ENTRY(HEART_BLOOD+3,HeartBlood3)
CONPIC_ENTRY(HEART_BLOOD+4,HeartBlood4)
CONPIC_ENTRY(HEART_BLOOD+5,HeartBlood5)

#undef CONPIC_ENTRY