code:
/*
    Build Game Customization Suite
    Copyright (c) 1999, 2004 Jonathon Fowler

    15 September 2004

    This is the source code to BCS. It was written in Borland Turbo C++ for DOS
    and [was] a 16bit real-mode DOS application. I'm releasing the code because
    I have no reason to keep it a secret. Some folks might find it interesting.

    BTW, you can use this code for any purpose you want.

    Jonathon Fowler
    jf@jonof.id.au
    http://www.jonof.id.au/
*/
/*
    NOTE: This program does not fall under BUILDLIC.
*/
// DOS 16-bit real mode UI --> portable command line conversion by Hendricks266

#include "compat.h"

const char APP_NAME[] = "Build Game Customization Suite v0.2-EDuke32";
const char APP_CPRT[] = "Copyright (c) 1999, 2004 Jonathon Fowler";

int bsExtractD3DPalette(int, const char*);
int bsUpdateD3DPalette(int, const char*);

int bsExtractPalette(const char*);
int bsUpdatePalette(const char*);

const char *MainMenuStrings[] = {
        "Options:",
        "Extract Duke Nukem 3D-specific Palettes",
        "Update Duke Nukem 3D-specific Palettes",
        "Extract Build Game Palette",
        "Update Build Game Palette"
};

const char *D3DMenuStrings[] = {
        "Sub-Option: Duke Nukem 3D-specific Palettes:",
        "Water Palette",
        "Night-Vision Palette",
        "Title Screen Palette",
        "3D Realms Logo Palette",
        "Episode 1 Ending Animation Palette"
};

const char *pal_deffn[] = {
        "GAME.PAL",
        "D3DWATER.PAL",
        "D3DNVIS.PAL",
        "D3DTITLE.PAL",
        "D3D3DR.PAL",
        "D3DEP1.PAL"
    };

int main(const int32_t argc, const char **argv)
{
    int opt = 0, d3dpal = 0, k = 0;
    int16_t i = 1;
    char const * filename = NULL; // This is only a pointer. Do not strcpy to it.
    char const * c = NULL;

    Bprintf("%s\n%s\n\n", APP_NAME, APP_CPRT);

    if (argc > 1)
    {
        opt = Bstrtol(argv[i++],NULL,10);
        if ((opt == 1 || opt == 2) && i < argc) // Duke-specific palettes
            d3dpal = Bstrtol(argv[i++],NULL,10);

        while (i < argc)
        {
            c = (char const *)argv[i];
            if ((*c == '-')
#ifdef _WIN32
                    || (*c == '/')
#endif
               )
            {
                ++c;
                if (!Bstrcasecmp(c,"f"))
                {
                    if (argc > i+1)
                        filename = (char const *)argv[++i];
                    ++i;
                    continue;
                }

            }
            ++i;
        }
    }

    if (opt < 1 || opt > 4 || (opt < 3 && (d3dpal < 1 || d3dpal > 5)))
    {
        Bprintf("usage: %s <option> <sub-option(s)> [-f filename]\n",argv[0]);
        Bprintf("If a filename is not specified, internal defaults will be used.\n");
        Bprintf("\n");
        for (k = 0; k < 5; ++k)
        {
            if (k > 0)
                Bprintf("%d - ",k);
            Bprintf("%s\n",MainMenuStrings[k]);
        }
        Bprintf("\n");
        for (k = 0; k < 6; ++k)
        {
            if (k > 0)
                Bprintf("%d - ",k);
            Bprintf("%s\n",D3DMenuStrings[k]);
        }
        Bprintf("\n");
/*
        Bprintf(          "This program is, well, I guess freeware. Questions, suggestions,\n"
                         "comments and bug reports are welcome at jf@jonof.id.au. Visit\n"
                         "my website at http://www.jonof.id.au/ for more information\n"
                         "on this program and others that I may happen to write.\n\n");
*/
    }
    else
    {
        if (filename == NULL)
            switch (opt)
            {
                case 1: // Duke-specific palettes
                case 2:
                    filename = (char const *)pal_deffn[d3dpal];
                    break;

                case 3: // game palette
                case 4:
                    filename = (char const *)pal_deffn[0];
                    break;
            }

        switch (opt)
        {
            case 1: // extract Duke-specific palettes
                bsExtractD3DPalette(d3dpal-1, filename);
                break;

            case 2: // update Duke-specific palettes
                bsUpdateD3DPalette(d3dpal-1, filename);
                break;

            case 3: // extract game palette
                bsExtractPalette(filename);
                break;

            case 4: // update game palette
                bsUpdatePalette(filename);
                break;
        }
    }

    return 0;
}

const int pal_offsets[5] = {6426, 7194, 7962, 8730, 9498};

#define PAL_LEN            768

/////////////////////////////////////////////////
//
// Extract and update functions

int bsExtractD3DPalette(int palnum, const char *outfn)
{
    BFILE *lookup, *out;
    char cb[3];
    int lp;

    Bprintf("Using: %s\n",outfn);

    lookup = Bfopen("LOOKUP.DAT", "rb");
    if (lookup == NULL)
    {
        // could not open LOOKUP.DAT
        Bprintf("Error opening LOOKUP.DAT!\n"
                            "Make sure that the file is in the current\n"
                            "directory, then try again.\n\n");

        return 1;
    }

    // create output file
    out = Bfopen(outfn, "w+t");
    if (out == NULL)
    {
        Bfclose(lookup);
        Bprintf("Error creating output file!\n"
                            "The file may be open by another program\n"
                            "or is read-only, or the disk may be read-only.\n\n");
        return 1;
    }

    // write out the palette data in PSP format

    // find palette data
    Bfseek(lookup, pal_offsets[palnum], SEEK_SET);

    // write out a Paint Shop Pro palette file
    Bfprintf(out, "JASC-PAL\n0100\n256\n");
    for (lp=0; lp < 256; lp++)
    {
        cb[0] = Bfgetc(lookup) * 4;
        cb[1] = Bfgetc(lookup) * 4;
        cb[2] = Bfgetc(lookup) * 4;

        Bfprintf(out, "%d %d %d\n", cb[0], cb[1], cb[2]);
    }

    // close files
    Bfclose(out);
    Bfclose(lookup);

    Bprintf("Palette dumped successfully!\n\n");

    return 0;
}

int bsUpdateD3DPalette(int palnum, const char *palfn)
{
    BFILE *lookup, *pal;
    char cb[3], work[64];
    int lp;

    Bprintf("Using: %s\n",palfn);

    lookup = Bfopen("LOOKUP.DAT", "r+b");
    if (lookup == NULL)
    {
        // could not open LOOKUP.DAT
        Bprintf("Error opening LOOKUP.DAT!\n"
                            "The file may be open by another program\n"
                            "or is read-only, or the disk may be read-only.\n\n");

        return 1;
    }

    // open source file
    pal = Bfopen(palfn, "rt");
    if (pal == NULL)
    {
        Bfclose(lookup);
        Bprintf("Error opening palette file!\n"
                            "Make sure that the file exists.\n\n");
        return 1;
    }

    // read the palette data and write it to LOOKUP.DAT

    Bfgets(work, 64, pal);
    if (strncmp(work, "JASC-PAL", 8))
    {
        Bfclose(pal); Bfclose(lookup);
        Bprintf("Error validating palette file!\n"
                            "This palette file appears to be in a format\n"
                            "other than Paint Shop Pro format. This program\n"
                            "works only with Paint Shop Pro palette files.\n\n");
        return 1;
    }

    Bfgets(work, 64, pal);
    if (strncmp(work, "0100", 4))
    {
        Bfclose(pal); Bfclose(lookup);
        Bprintf("Error validating palette file!\n"
                            "This palette file appears to be in a version\n"
                            "other than 0100. This program works only with\n"
                            "Paint Shop Pro palettes of version 0100.\n\n");
        return 1;
    }

    Bfgets(work, 64, pal);
    if (strncmp(work, "256", 3))
    {
        Bfclose(pal); Bfclose(lookup);
        Bprintf("Error validating palette file!\n"
                            "This palette file appears to be for a palette\n"
                            "size other than 256 colours. This program works\n"
                            "only with Paint Shop Pro palettes of 256 colours.\n\n");
        return 1;
    }

    // find palette data
    Bfseek(lookup, pal_offsets[palnum], SEEK_SET);

    // write out new palette info
    for (lp=0; lp < 256; lp++)
    {
        Bfscanf(pal, "%c %c %c\n", &cb[0], &cb[1], &cb[2]);

        Bfputc(cb[0] / 4, lookup);
        Bfputc(cb[1] / 4, lookup);
        Bfputc(cb[2] / 4, lookup);
    }

    // close files
    Bfclose(pal);
    Bfclose(lookup);

    Bprintf("Palette updated successfully!\n\n");

    return 0;
}

// Format of PALETTE.DAT files
//
//   256 bytes     - palette
//   2 bytes       - short: number of palette lookups
//   n*256 bytes   - shading lookup tables
//   256*256 bytes - translucency lookup array

int bsExtractPalette(const char *outfn)
{
    BFILE *palette, *out;
    char cb[3];
    int lp;

    Bprintf("Using: %s\n",outfn);

    palette = Bfopen("PALETTE.DAT", "rb");
    if (palette == NULL)
    {
        // could not open PALETTE.DAT
        Bprintf("Error opening PALETTE.DAT!\n"
                            "Make sure that the file is in the current\n"
                            "directory, then try again.\n\n");

        return 1;
    }

    // create output file
    out = Bfopen(outfn, "w+t");
    if (out == NULL)
    {
        Bfclose(palette);
        Bprintf("Error creating output file!\n"
                            "The file may be open by another program\n"
                            "or is read-only, or the disk may be read-only.\n\n");
        return 1;
    }

    // write out the palette data in PSP format

    // write out a Paint Shop Pro palette file
    Bfprintf(out, "JASC-PAL\n0100\n256\n");
    for (lp=0; lp < 256; lp++)
    {
        cb[0] = Bfgetc(palette) * 4;
        cb[1] = Bfgetc(palette) * 4;
        cb[2] = Bfgetc(palette) * 4;

        Bfprintf(out, "%d %d %d\n", cb[0], cb[1], cb[2]);
    }

    // close files
    Bfclose(out);
    Bfclose(palette);

    Bprintf("Palette dumped successfully!\n\n");

    return 0;
}

int bsUpdatePalette(const char *palfn)
{
    BFILE *palette, *pal;
    char cb[3], work[64];
    int lp;

    Bprintf("Using: %s\n",palfn);

    palette = Bfopen("PALETTE.DAT", "w+b");
    if (palette == NULL)
    {
        // could not open LOOKUP.DAT
        Bprintf("Error opening PALETTE.DAT!\n"
                            "The file may be open by another program\n"
                            "or is read-only, or the disk may be read-only.\n\n");

        return 1;
    }

    // open source file
    pal = Bfopen(palfn, "rt");
    if (pal == NULL)
    {
        Bfclose(palette);
        Bprintf("Error opening palette file!\n"
                            "Make sure that the file exists.\n\n");
        return 1;
    }

    // read the palette data and write it to PALETTE.DAT

    Bfgets(work, 64, pal);
    if (strncmp(work, "JASC-PAL", 8))
    {
        Bfclose(pal); Bfclose(palette);
        Bprintf("Error validating palette file!\n"
                            "This palette file appears to be in a format\n"
                            "other than Paint Shop Pro format. This program\n"
                            "works only with Paint Shop Pro palette files.\n\n");
        return 1;
    }

    Bfgets(work, 64, pal);
    if (strncmp(work, "0100", 4))
    {
        Bfclose(pal); Bfclose(palette);
        Bprintf("Error validating palette file!\n"
                            "This palette file appears to be in a version\n"
                            "other than 0100. This program works only with\n"
                            "Paint Shop Pro palettes of version 0100.\n\n");
        return 1;
    }

    Bfgets(work, 64, pal);
    if (strncmp(work, "256", 3))
    {
        Bfclose(pal); Bfclose(palette);
        Bprintf("Error validating palette file!\n"
                            "This palette file appears to be for a palette\n"
                            "size other than 256 colours. This program works\n"
                            "only with Paint Shop Pro palettes of 256 colours.\n\n");
        return 1;
    }

    // write out new palette info
    for (lp=0; lp < 256; lp++)
    {
        Bfscanf(pal, "%c %c %c\n", &cb[0], &cb[1], &cb[2]);

        // put the bytes into the basergb array as well
        Bfputc(cb[0] / 4, palette);
        Bfputc(cb[1] / 4, palette);
        Bfputc(cb[2] / 4, palette);
    }

    // close files
    Bfclose(pal);
    Bfclose(palette);

    Bprintf("Palette updated successfully!\n"
                        "Now run TRANSPAL.EXE to create the shading\n"
                        "and translucency tables for the palette.\n\n");

    return 0;
}


code:
// XXX: This program is not in sync with EDuke32 (e.g. texcacheheader type).

#include "compat.h"
#include <dirent.h>

#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT   0x83F0
#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT  0x83F1
#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT  0x83F2
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT  0x83F3

typedef struct {
    char magic[8];    // 'Polymost'
    int xdim, ydim;    // of image, unpadded
    int flags;        // 1 = !2^x, 2 = has alpha, 4 = lzw compressed
} texcacheheader;
typedef struct {
    int size;
    int format;
    int xdim, ydim;    // of mipmap (possibly padded)
    int border, depth;
} texcachepicture;

int main(void)
{
    DIR *dir;
    struct dirent *dirent;
    struct stat st;
    FILE *fp;
    texcacheheader head;
    texcachepicture mip;

    dir = opendir(".");
    while ((dirent = readdir(dir))) {
        if (stat(dirent->d_name, &st)) {
            printf("%s: failed to stat\n", dirent->d_name);
            continue;
        }
        if (!(st.st_mode&S_IFREG)) {
            printf("%s: not a regular file\n", dirent->d_name);
            continue;
        }

        fp = fopen(dirent->d_name,"rb");
        if (!fp) {
            printf("%s: failed to open\n", dirent->d_name);
            continue;
        }

        if (fread(&head, sizeof(head), 1, fp) != 1) {
            fclose(fp);
            printf("%s: failed to read header\n", dirent->d_name);
            continue;
        }
        head.xdim = B_LITTLE32(head.xdim);
        head.ydim = B_LITTLE32(head.ydim);
        head.flags = B_LITTLE32(head.flags);
        if (fread(&mip, sizeof(mip), 1, fp) != 1) {
            fclose(fp);
            printf("%s: failed to read mipmap header\n", dirent->d_name);
            continue;
        }
        mip.format = B_LITTLE32(mip.format);
        fclose(fp);
        if (memcmp(head.magic, "Polymost", 8)) {
            printf("%s: bad signature\n", dirent->d_name);
            continue;
        }
        else {
            char const * format;
            char flags[4] = "", flagsc = 0;
            switch (mip.format) {
                case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: format = "RGB DXT1"; break;
                case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: format = "RGBA DXT1"; break;
                case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: format = "RGBA DXT3"; break;
                case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: format = "RGBA DXT5"; break;
                default: format = "Unknown"; break;
            }
            if (head.flags&1) flags[flagsc++] = '2';
            if (head.flags&2) flags[flagsc++] = 'A';
            if (head.flags&4) flags[flagsc++] = 'L';
            flags[flagsc++] = 0;

            printf("%s: flags=%s format=%s\n", dirent->d_name, flags, format);
        }
    }
    closedir(dir);

    return 0;
}

repo_name: orochi/nblood

license: mit


code:
#!/bin/bash

function usage ()
{
    echo 'Usage: checkdefs.sh <some.def> [[<search_path_base_dir>] {-patch,-con,-conpatch}]'
    exit 1
}

if [ -z "$1" ]; then
    usage
fi
deffn="$1"

if [ ! -f "$deffn" ]; then
    echo "Error: First argument must be a name of an existing DEF or CON file."
    usage
fi

if [ -z "$2" ]; then
    thedir=.
else
    thedir="$2"
fi

if [ ! -d "$thedir" ]; then
    echo "Error: Second argument must be a name of an existing directory."
    usage
fi

dopatch=""
docon=""
if [ -n "$3" ]; then
    if [ "$3" != "-patch" -a "$3" != "-con" -a "$3" != "-conpatch" ]; then
        echo 'Usage: checkdefs.sh <some.def> [[<search_path_base_dir>] {-patch,-con,-conpatch}]'
        exit 1
    fi
    if [ "$3" == "-patch" ]; then
        dopatch=1
    elif [ "$3" == "-con" ]; then
        docon=1
    else
        docon=1
        dopatch=1
    fi
fi

if [ -z $docon ]; then
    # def
    files=$(grep -E "\"[^ ]*\..*\"" "$deffn" | sed 's/.*"\(.*\..*\)".*/\1/g')
    files2=$(grep -E '^include ' "$deffn" | sed 's/^include \(.*\)\r/\1/g')  # XXX: \r

    files="$files $files2"
else
    # con... this is awful
    files=$(grep -E -i '(include *.*\.con)|(definesound.*(voc|wav|ogg))|(definelevelname.*\.map)' "$deffn" |
        sed -r 's/.*include[ \t]+([^ \t]+\.[cC][oO][nN]).*/\1/g;
                s/.*[ \t]([^ \t].+\.([wW][aA][vV]|[vV][oO][cC]|[oO][gG][gG])).*/\1/g;
                s/.*[ \t]([^ \t].+\.([mM][aA][pP])).*/\1/g;')
fi

exfiles=$(find -L "$thedir" -type f)

sedcmd=""

for i in $files; do
    fn="$thedir/$i"
    if [ ! -f "$fn" ]; then
        # try finding a matching file
        match=$(echo "$exfiles" | grep -i "^$fn$")

        if [ -z "$match" ]; then
            if [ -z "$docon" ]; then  # avoid spamming files not found that are in GRPs...
                echo "$fn"
            fi
        else
            echo "$fn --> $match"
            if [ -n "$dopatch" ]; then
                if [ -z "$docon" ]; then
                    sedcmd="$sedcmd;s|\"$i\"|\"${match#$thedir/}\"|g"
                else
                    sedcmd="$sedcmd;s|$i|${match#$thedir/}|g"
                fi
            fi
        fi
    fi
done

if [ -n "$dopatch" ]; then
    if [ -n "$sedcmd" ]; then
        echo "Patching $deffn"
#        echo "$sedcmd"
        sed -i "$sedcmd" "$deffn"
    fi
fi


code:
// Compatibility declarations for the tools to avoid linking to the entire engine.

#include "compat.h"

#ifdef __cplusplus
extern "C" {
#endif

//
// initprintf() -- prints a string
//
int initprintf(const char *f, ...)
{
    va_list va;
    char buf[2048];

    va_start(va, f);
    int len = Bvsnprintf(buf, sizeof(buf), f, va);
    va_end(va);

    return len;
}

void initputs (const char * str) { puts(str); }

int16_t editstatus = 1;

#ifdef __cplusplus
}
#endif


code:
#include "compat.h"

#define NEED_DDRAW_H
#include "windows_inc.h"

#define DEFAULT_OUTPUT_FILE "enumdisplay.txt"

HMODULE      hDDrawDLL = NULL;
LPDIRECTDRAW lpDD      = NULL;
FILE *output = NULL;

void usage(void)
{
    printf(
    "enumdisplay by Jonathon Fowler (jf@jonof.id.au)\n"
    "Options:\n"
    "   -h, -?, --help     This message\n"
    "   -o <filename>      Use different output file (default: "
        DEFAULT_OUTPUT_FILE ", use - for stdout)\n"
          );
}

void dumpdevmode(DEVMODE *devmode)
{
    fprintf(output, "\tdmFields has");
    if (devmode->dmFields & DM_PELSWIDTH) fprintf(output, " DM_PELSWIDTH");
    if (devmode->dmFields & DM_PELSHEIGHT) fprintf(output, " DM_PELSHEIGHT");
    if (devmode->dmFields & DM_BITSPERPEL) fprintf(output, " DM_BITSPERPEL");
    fprintf(output, "\n\tdmPelsWidth = %lu\n", devmode->dmPelsWidth);
    fprintf(output, "\tdmPelsHeight = %lu\n", devmode->dmPelsHeight);
    fprintf(output, "\tdmBitsPerPel = %lu\n", devmode->dmBitsPerPel);
}

HRESULT WINAPI ddenum(DDSURFACEDESC *ddsd, VOID *udata ATTRIBUTE((unused)))
{
    fprintf(output, "\tdwFlags has");
    if (ddsd->dwFlags & DDSD_WIDTH) fprintf(output, " DDSD_WIDTH");
    if (ddsd->dwFlags & DDSD_HEIGHT) fprintf(output, " DDSD_HEIGHT");
    if (ddsd->dwFlags & DDSD_PIXELFORMAT) fprintf(output, " DDSD_PIXELFORMAT");
    fprintf(output, "\n\tdwWidth = %lu\n", ddsd->dwWidth);
    fprintf(output, "\tdwHeight = %lu\n", ddsd->dwHeight);
    fprintf(output, "\tddpfPixelFormat.dwFlags has");
    if (ddsd->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED1) fprintf(output, " DDPF_PALETTEINDEXED1");
    if (ddsd->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED2) fprintf(output, " DDPF_PALETTEINDEXED2");
    if (ddsd->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4) fprintf(output, " DDPF_PALETTEINDEXED4");
    if (ddsd->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) fprintf(output, " DDPF_PALETTEINDEXED8");
    if (ddsd->ddpfPixelFormat.dwFlags & DDPF_RGB) fprintf(output, " DDPF_RGB");
    fprintf(output, "\n\tddpfPixelFormat.dwRGBBitCount = %lu\n", ddsd->ddpfPixelFormat.dwRGBBitCount);
    fprintf(output, "\n");

    return(DDENUMRET_OK);
}

typedef HRESULT (WINAPI *aDirectDrawCreateType)(GUID *, LPDIRECTDRAW *, IUnknown *);
typedef HRESULT (WINAPI *aDirectDrawEnumerateType)(LPDDENUMCALLBACK, LPVOID);

int InitDirectDraw(void)
{
    HRESULT result;
    aDirectDrawCreateType aDirectDrawCreate;
    aDirectDrawEnumerateType aDirectDrawEnumerate;

    hDDrawDLL = LoadLibrary("DDRAW.DLL");
    if (!hDDrawDLL) { fprintf(output, "Failed loading DDRAW.DLL\n"); return -1; }

    aDirectDrawEnumerate = (aDirectDrawEnumerateType)(void (*)(void))GetProcAddress(hDDrawDLL, "DirectDrawEnumerateA");
    if (!aDirectDrawEnumerate) { fprintf(output, "Error fetching DirectDrawEnumerate\n"); return -1; }

    aDirectDrawCreate = (aDirectDrawCreateType)(void (*)(void))GetProcAddress(hDDrawDLL, "DirectDrawCreate");
    if (!aDirectDrawCreate) { fprintf(output, "Error fetching DirectDrawCreate\n"); return -1; }

    result = aDirectDrawCreate(NULL, &lpDD, NULL);
    if (result != DD_OK) { fprintf(output, "DirectDrawCreate() failed (%ld)\n", result); return -1; }

    return 0;
}

void UninitDirectDraw(void)
{
    if (lpDD) IDirectDraw_Release(lpDD);
    lpDD = NULL;
    if (hDDrawDLL) FreeLibrary(hDDrawDLL);
    hDDrawDLL = NULL;
}

int main(int argc, char **argv)
{
    char const * outputfile = DEFAULT_OUTPUT_FILE;

    int i;

    DEVMODE devmode;
    HRESULT hresult;

    for (i=1; i<argc; i++) {
        if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-?") || !strcmp(argv[i], "--help")) {
            usage();
            return 0;
        } else if (!strcmp(argv[i], "-o")) {
            outputfile = argv[++i];
        }
    }

    if (!strcmp(outputfile, "-")) {
        output = fdopen(1, "wt");
        outputfile = NULL;
    } else {
        output = fopen(outputfile, "wt");
        if (!output) {
            fprintf(stderr, "enumdisplay: failed to open %s for output\n", outputfile);
            return 1;
        }
    }

    fprintf(output,
        "enumdisplay results\n"
        "\n"
        "Display settings:\n"
           );
    ZeroMemory(&devmode, sizeof(devmode));
    devmode.dmSize = sizeof(DEVMODE);
    if (!EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devmode)) {
        fprintf(output, "\tEnumDisplaySettings() FAILED!\n");
    } else {
        dumpdevmode(&devmode);
    }

    fprintf(output,
        "\n"
        "All modes from EnumDisplaySettings:\n"
           );
    ZeroMemory(&devmode, sizeof(devmode));
    devmode.dmSize = sizeof(DEVMODE);
    i = 0;
    while (EnumDisplaySettings(NULL, i, &devmode)) {
        dumpdevmode(&devmode);
        fprintf(output, "\n");
        ZeroMemory(&devmode, sizeof(devmode));
        devmode.dmSize = sizeof(DEVMODE);
        i++;
    }

    if (!InitDirectDraw()) {
        fprintf(output,
            "\n"
            "All modes from IDirectDraw::EnumDisplayModes:\n"
               );
        hresult = IDirectDraw_EnumDisplayModes(lpDD, 0, NULL, (LPVOID)0, ddenum);
        if (hresult != DD_OK) {
            fprintf(output, "\tIDirectDraw::EnumDisplayModes() FAILED! (%ld)\n", hresult);
        }
    }
    UninitDirectDraw();

    if (outputfile) fclose(output);

    return 0;
}


code:
#include "compat.h"
#include "kplib.h"

struct icon {
    int32_t width,height;
    intptr_t *pixels;
    unsigned char *mask;
};

int writeicon(FILE *fp, struct icon *ico)
{
    int i;

    Bfprintf(fp,
        "#include \"sdl_inc.h\"\n"
        "#include \"sdlappicon.h\"\n"
        "\n"
    );
    Bfprintf(fp,"static Uint8 sdlappicon_pixels[] = {\n");
    for (i=0;i<ico->width*ico->height;i++) {
        if ((i%6) == 0) Bfprintf(fp,"\t");
        else Bfprintf(fp," ");
        Bfprintf(fp, "0x%08lx,", (long)B_LITTLE32(ico->pixels[i]));
        if ((i%6) == 5) Bfprintf(fp,"\n");
    }
    if ((i%16) > 0) Bfprintf(fp, "\n");
    Bfprintf(fp, "};\n\n");

    Bfprintf(fp,
        "struct sdlappicon sdlappicon = {\n"
        "    %d,%d,    // width,height\n"
        "    sdlappicon_pixels\n"
        "};\n",
        ico->width, ico->height
    );

    return 0;
}

int main(int argc, char **argv)
{
    struct icon icon;

    if (argc<2) {
        Bfprintf(stderr, "generateicon <picture file>\n");
        return 1;
    }

    memset(&icon, 0, sizeof(icon));

    engineCreateAllocator();
    kpzload(argv[1], (intptr_t*)&icon.pixels, &icon.width, &icon.height);
    if (!icon.pixels) {
        Bfprintf(stderr, "Failure loading %s\n", argv[1]);
        return 1;
    }

    writeicon(stdout, &icon);

    xfree(icon.pixels);

    return 0;
}


code:
// compile with:
// gcc -o getdxdidf.exe src\getdxdidf.c -Ic:\mingw32\dx6\include -Lc:\mingw32\dx6\lib -ldxguid -ldinput -mwindows

#include "compat.h"

#define NEED_DINPUT_H
#include "windows_inc.h"

char const * WhatGUID(const GUID *guid)
{
    if (guid == &GUID_XAxis) return "&GUID_XAxis";
    if (guid == &GUID_YAxis) return "&GUID_YAxis";
    if (guid == &GUID_ZAxis) return "&GUID_ZAxis";
    if (guid == &GUID_RxAxis) return "&GUID_RxAxis";
    if (guid == &GUID_RyAxis) return "&GUID_RyAxis";
    if (guid == &GUID_RzAxis) return "&GUID_RzAxis";
    if (guid == &GUID_Slider) return "&GUID_Slider";

    if (guid == &GUID_Button) return "&GUID_Button";
    if (guid == &GUID_Key) return "&GUID_Key";

    if (guid == &GUID_POV) return "&GUID_POV";

    if (guid == &GUID_Unknown) return "&GUID_Unknown";

    return "NULL";
}

int WINAPI WinMain(HINSTANCE hInstance ATTRIBUTE((unused)), HINSTANCE hPrevInstance ATTRIBUTE((unused)), LPSTR lpCmdLine ATTRIBUTE((unused)), int nCmdShow ATTRIBUTE((unused)))
{
    FILE *fp;
    DWORD i;

    fp = fopen("didf.txt", "w");
    if (!fp) return -1;
    setvbuf(fp, NULL, _IONBF, 0);

    fprintf(fp,
        "// Keyboard\n"
        "\n"
        "static DIOBJECTDATAFORMAT c_dfDIKeyboard_odf[] = {\n"
        );

    for (i=0; i<c_dfDIKeyboard.dwNumObjs; i++) {
        fprintf(fp,
            "\t{ %s, %lu, 0x%08lu, 0x%08lu },\n",
                WhatGUID(c_dfDIKeyboard.rgodf[i].pguid),
                c_dfDIKeyboard.rgodf[i].dwOfs,
                c_dfDIKeyboard.rgodf[i].dwType,
                c_dfDIKeyboard.rgodf[i].dwFlags
            );
    }
    fprintf(fp,
        "};\n"
        "\n"
        "const DIDATAFORMAT c_dfDIKeyboard = { %lu, %lu, 0x%08lu, %lu, %lu, c_dfDIKeyboard_odf };\n\n",
        c_dfDIKeyboard.dwSize,
            c_dfDIKeyboard.dwObjSize,
            c_dfDIKeyboard.dwFlags,
            c_dfDIKeyboard.dwDataSize,
            c_dfDIKeyboard.dwNumObjs
        );

    fprintf(fp,
        "// Mouse\n"
        "\n"
        "static DIOBJECTDATAFORMAT c_dfDIMouse_odf[] = {\n"
        );

    for (i=0; i<c_dfDIMouse.dwNumObjs; i++) {
        fprintf(fp,
            "\t{ %s, %lu, 0x%08lu, 0x%08lu },\n",
                WhatGUID(c_dfDIMouse.rgodf[i].pguid),
                c_dfDIMouse.rgodf[i].dwOfs,
                c_dfDIMouse.rgodf[i].dwType,
                c_dfDIMouse.rgodf[i].dwFlags
            );
    }
    fprintf(fp,
        "};\n"
        "\n"
        "const DIDATAFORMAT c_dfDIMouse = { %lu, %lu, 0x%08lu, %lu, %lu, c_dfDIMouse_odf };\n\n",
        c_dfDIMouse.dwSize,
            c_dfDIMouse.dwObjSize,
            c_dfDIMouse.dwFlags,
            c_dfDIMouse.dwDataSize,
            c_dfDIMouse.dwNumObjs
        );

    fprintf(fp,
        "// Joystick\n"
        "\n"
        "static DIOBJECTDATAFORMAT c_dfDIJoystick_odf[] = {\n"
        );

    for (i=0; i<c_dfDIJoystick.dwNumObjs; i++) {
        fprintf(fp,
            "\t{ %s, %lu, 0x%08lu, 0x%08lu },\n",
                WhatGUID(c_dfDIJoystick.rgodf[i].pguid),
                c_dfDIJoystick.rgodf[i].dwOfs,
                c_dfDIJoystick.rgodf[i].dwType,
                c_dfDIJoystick.rgodf[i].dwFlags
            );
    }
    fprintf(fp,
        "};\n"
        "\n"
        "const DIDATAFORMAT c_dfDIJoystick = { %lu, %lu, 0x%08lu, %lu, %lu, c_dfDIJoystick_odf };\n\n",
        c_dfDIJoystick.dwSize,
            c_dfDIJoystick.dwObjSize,
            c_dfDIJoystick.dwFlags,
            c_dfDIJoystick.dwDataSize,
            c_dfDIJoystick.dwNumObjs
        );

    fclose(fp);

    return 0;
}


code:
#include "compat.h"

#define MAXNUMTILES 256

int artversion, numtiles;
int localtilestart, localtileend;
short tilesizx[MAXNUMTILES], tilesizy[MAXNUMTILES];
int picanm[MAXNUMTILES];

FILE * openartfile(char *fn)
{
    FILE *fh;

    fh = fopen(fn,"rb");
    if (!fh) return NULL;

    fread(&artversion,4,1,fh); if (artversion != 1) { puts("Bad art version"); goto fail; }
    fread(&numtiles,4,1,fh);
    fread(&localtilestart,4,1,fh);
    fread(&localtileend,4,1,fh);
    numtiles = localtileend-localtilestart+1;
    if (numtiles > MAXNUMTILES) { puts("Too many tiles"); goto fail; }
    fread(tilesizx,2,numtiles,fh);
    fread(tilesizy,2,numtiles,fh);
    fread(picanm,4,numtiles,fh);

    return fh;
fail:
    fclose(fh);
    return NULL;
}

int main(int argc, char **argv)
{
    char const * palfile = "palette.dat", * voxfile = "output.vox";
    int tilenum;
    int depth;
    FILE *artfh, *voxfh, *palfh;
    int tilesz;
    unsigned char palette[768];
    unsigned char *tiledata;
    int i;

    if (argc < 4) {
        puts("givedepth <artfile.art> <tilenum> <depth> [palette.dat] [output.vox]");
        return 0;
    }

    tilenum = atoi(argv[2]);
    depth = atoi(argv[3]);
    if (argc >= 4) palfile = argv[4];
    if (argc >= 5) voxfile = argv[5];

    palfh = fopen(palfile,"rb");
    if (!palfh) {
        puts("Failure opening palette file");
        return 1;
    }
    fread(palette,768,1,palfh);
    fclose(palfh);

    artfh = openartfile(argv[1]);
    if (!artfh) {
        puts("Failure opening art file");
        return 1;
    }

    if (tilenum < 0 || tilenum > numtiles) {
        puts("Tilenum out of range in art file");
        fclose(artfh);
        return 1;
    }
    for (i=0; i<tilenum; i++) fseek(artfh, tilesizx[i] * tilesizy[i], SEEK_CUR);

    tilesz = tilesizx[tilenum]*tilesizy[tilenum];
    tiledata = (unsigned char *)malloc(tilesz);
    if (!tiledata) {
        puts("Could not allocate memory for tile");
        fclose(artfh);
        return 1;
    }

    fread(tiledata, tilesz, 1, artfh);
    fclose(artfh);

    voxfh = fopen(voxfile,"wb");
    if (!voxfh) {
        puts("Could not create output file");
        free(tiledata);
        return 1;
    }
    fwrite(&depth,4,1,voxfh);
    fwrite(&tilesizx[tilenum],4,1,voxfh);
    fwrite(&tilesizy[tilenum],4,1,voxfh);
    for (i=0; i<depth; i++) {
        fwrite(tiledata,tilesz,1,voxfh);
    }
    fwrite(palette,768,1,voxfh);

    free(tiledata);

    return 0;
}


code:
#!/usr/bin/python

def makehighpalookuppixel(pal, rgb):
    hsv = list(colorsys.rgb_to_hsv(*rgb))
    if pal == 0:
        # no-op, pass through
        return rgb
    # frozen, blue light
    elif pal == 1:
        # make everything blueish
        hsv[0] = 0.66
        return list(colorsys.hsv_to_rgb(*hsv))
    # nightvision
    elif pal == 6:
        # make everything green and reverse brightness
        hsv[0] = 0.33
        hsv[2] = 1.0 - hsv[2]
        #hsv[1] = 0.5
        return list(colorsys.hsv_to_rgb(*hsv))
    # pal 20
    elif pal == 20:
        # blue to gray by removing all saturation
        if (hsv[0] > 0.6 and hsv[0] < 0.7):
            hsv[1] = 0
        # orange and brown to blue
        if (hsv[0] > 0.04 and hsv[0] < 0.13):
            hsv[0] = 0.66
        # purple and reddish to blue
        if (hsv[0] > 0.7 and hsv[0] < 0.9):
            hsv[0] = 0.66
        # green to blue
        if (hsv[0] > 0.30 and hsv[0] < 0.36):
            hsv[0] = 0.66
        return list(colorsys.hsv_to_rgb(*hsv))
    else:
        print "unknown pal!"
        sys.exit()

import colorsys
import sys
import struct

if (len(sys.argv) != 3):
    print "Usage: python highpalookupmaker.py palnum outfile"
    sys.exit()

# bit depth per dimension
xbits = 7
ybits = 7
zbits = 7

xdim = 1 << xbits
ydim = 1 << ybits
zdim = 1 << zbits

palnum = int(sys.argv[1])

pixels = []
pixelcount = xdim * ydim * zdim
curpix = 0.0

fo = open(sys.argv[2], "w")

# throw in a TGA header in there, this way they'll be able to directly edit it if they feel like it
fo.write(struct.pack("=BBBHHBHHHHBB", 0, 0, 2, 0, 0, 0, 0, 0, 16384, 128, 32, 0))

print "Creating highpalookup map %s for palette %d with depth %d:%d:%d..." % (sys.argv[2], palnum, xbits, ybits, zbits)

for k in range(zdim):
    for j in range(ydim):
        for i in range(xdim):
            rgb = [float(i) / (xdim - 1), float(j) / (ydim - 1), float(k) / (zdim - 1)]
            rgb = makehighpalookuppixel(palnum, rgb)
            # save as BGRA as that's what TGA uses
            pixels.append(struct.pack('BBBB', int(rgb[2] * 255), int(rgb[1] * 255), int(rgb[0] * 255), 255))
            curpix += 1
            if (curpix % 128 == 0):
                print "\r%f%% done." % (curpix * 100 / pixelcount),

fo.writelines(pixels)
fo.close()

print "\n"


code:
#include "compat.h"
#ifndef USE_OPENGL
# define USE_OPENGL
#endif
#define ANIMVPX_STANDALONE
#include "animvpx.h"

static void print_info(const char *prefix, const animvpx_ivf_header_t *hdr)
{
    printf("%s%d x %d, %d frames @ %d frames / %d seconds (%.3f fps%s)\n", prefix,
           hdr->width, hdr->height, hdr->numframes, hdr->fpsnumer, hdr->fpsdenom,
           (hdr->fpsdenom==0 ? 0 : (double)hdr->fpsnumer/hdr->fpsdenom),
           hdr->fpsnumer>=1000 ? " --> 30 fps" : "");
}

int main(int argc, char **argv)
{
    int fd, dowrite, err;
    animvpx_ivf_header_t hdr;

    union { uint16_t i; char c[2]; } u;
    u.c[0] = 1;
    u.c[1] = 0;
    if (u.i != 1)
    {
        fprintf(stderr, "This program is only for little-endian machines.\n");
        return 255;
    }

    if (argc == 2 && argv[1][0]=='-')
        goto usage;

    if (argc != 2 && argc != 4 && argc != 5)
    {
usage:
        fprintf(stderr, "Usage: %s <file.ivf> [<fpsnumerator> <fpsdenominator> [-force]]\n"
                " Without -force, <fpsnumerator> must be < 1000.\n"
                " If <fpsnumerator> is >= 1000, the actual frame rate\n"
                " is set to 30 fps on playback.\n",
                argv[0]);
        return 1;
    }

    dowrite = (argc >= 4);

    fd = open(argv[1], dowrite ? O_RDWR : O_RDONLY);
    if (fd < 0)
    {
        fprintf(stderr, "Could't open \"%s\" for %s: %s\n", argv[1],
                dowrite ? "reading/writing":"reading", strerror(errno));
        return 2;
    }

    if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr))
    {
        fprintf(stderr, "Couldn't read IVF header: %s\n", strerror(errno));
        return 3;
    }

    err = animvpx_check_header(&hdr);
    if (err)
    {
        fprintf(stderr, "Header check failed with code %d (not an IVF file?)\n", err);
        return 4;
    }

    if (!dowrite)
    {
        print_info("", &hdr);
    }
    else
    {
        unsigned long numer = strtoul(argv[2], NULL, 10);
        unsigned long denom = strtoul(argv[3], NULL, 10);
        uint32_t numer32=numer, denom32=denom;
        const int NUMER_OFS = 16;  //offsetof(animvpx_ivf_header_t, fpsnumer);

        if (denom == 0)
        {
            fprintf(stderr, "FPS denominator must not be zero!\n");
            return 4;
        }

        if (numer >= 1000 && (argc!=5 || strcmp(argv[4], "-force")))
        {
            fprintf(stderr, "FPS numerator must be < 1000, or -force must be passed as 5th arg.\n");
            return 5;
        }

        if (numer32 != numer || denom32 != denom)
        {
            fprintf(stderr, "Out of range number passed.\n");
            return 6;
        }

        print_info("Old: ", &hdr);
        hdr.fpsnumer = numer32;
        hdr.fpsdenom = denom32;
        print_info("New: ", &hdr);

        if (lseek(fd, NUMER_OFS, SEEK_SET) != NUMER_OFS)
        {
            fprintf(stderr, "lseek failed: %s\n", strerror(errno));
            return 7;
        }

        err = 0;
        err |= (write(fd, &numer32, 4) != 4);
        err |= (write(fd, &denom32, 4) != 4);

        if (err)
        {
            fprintf(stderr, "Warning: data not fully written.\n");
            return 8;
        }
    }

    return 0;
}


code:
// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
// Ken Silverman's official web site: "http://www.advsys.net/ken"
// See the included license file "BUILDLIC.TXT" for license info.
//
// This file has been modified from Ken Silverman's original release
// by Jonathon Fowler (jf@jonof.id.au)

#include "compat.h"
#include "kplib.h"

#include <utime.h>

#define MAXFILES 4096

static char buf[65536];

static int numfiles, anyfiles4extraction;
static char marked4extraction[MAXFILES];
static char filelist[MAXFILES][16];
static int fileoffs[MAXFILES+1], fileleng[MAXFILES];

void findfiles(const char *dafilespec)
{
    char t[13];
    int i;

    for(i=numfiles-1;i>=0;i--)
    {
        memcpy(t,filelist[i],12);
        t[12] = 0;

        if (Bwildmatch(t,dafilespec)) {
            marked4extraction[i] = 1;
            anyfiles4extraction = 1;
        }
    }
}

int main(int argc, char **argv)
{
    int i, j, k, l, fil, fil2;
    struct Bstat stbuf;

    int onlylist = (argc==2);

    if (argc < 2)
    {
        Bprintf("KEXTRACT <groupfile.grp> [@file or filespec...]           by Kenneth Silverman\n");
        Bprintf("   This program extracts files from a previously grouped group file.\n");
        Bprintf("   You can extract files using the ? and * wildcards.\n");
        Bprintf("   Ex: kextract stuff.dat tiles000.art nukeland.map palette.dat\n");
        Bprintf("         (stuff.dat is the group file, the rest are the files to extract)\n");
        Bprintf("       kextract stuff.grp\n");
        Bprintf("         (simply lists the contents of stuff.grp)\n");
        return(0);
    }

    if ((fil = Bopen(argv[1],BO_BINARY|BO_RDONLY,BS_IREAD)) == -1)
    {
        Bprintf("Error: %s could not be opened\n",argv[1]);
        return(0);
    }

    Bread(fil,buf,16);
    if ((buf[0] != 'K') || (buf[1] != 'e') || (buf[2] != 'n') ||
         (buf[3] != 'S') || (buf[4] != 'i') || (buf[5] != 'l') ||
         (buf[6] != 'v') || (buf[7] != 'e') || (buf[8] != 'r') ||
         (buf[9] != 'm') || (buf[10] != 'a') || (buf[11] != 'n'))
    {
        Bclose(fil);
        Bprintf("Error: %s not a valid group file\n",argv[1]);
        return(0);
    }
    numfiles = *((int*)&buf[12]); numfiles = B_LITTLE32(numfiles);

    Bread(fil,filelist,numfiles<<4);

    j = 0;
    for(i=0;i<numfiles;i++)
    {
        k = *((int*)&filelist[i][12]); k = B_LITTLE32(k);
        filelist[i][12] = 0;
        fileoffs[i] = j;
        j += k;
    }
    fileoffs[numfiles] = j;

    if (onlylist)
    {
        for (i=0; i<numfiles; i++)
            Bprintf("%s\t\t%d\n", filelist[i], fileoffs[i+1]-fileoffs[i]);

        return 0;
    }

    for(i=0;i<numfiles;i++) marked4extraction[i] = 0;

    anyfiles4extraction = 0;
    for(i=argc-1;i>1;i--)
    {
        if (argv[i][0] == '@')
        {
            if ((fil2 = Bopen(&argv[i][1],BO_BINARY|BO_RDONLY,BS_IREAD)) != -1)
            {
                l = Bread(fil2,buf,65536);
                j = 0;
                while ((j < l) && (buf[j] <= 32)) j++;
                while (j < l)
                {
                    k = j;
                    while ((k < l) && (buf[k] > 32)) k++;

                    buf[k] = 0;
                    findfiles(&buf[j]);
                    j = k+1;

                    while ((j < l) && (buf[j] <= 32)) j++;
                }
                Bclose(fil2);
            }
        }
        else
            findfiles(argv[i]);
    }

    if (anyfiles4extraction == 0)
    {
        Bclose(fil);
        Bprintf("No files found in group file with those names\n");
        return(0);
    }

    if (Bfstat(fil, &stbuf) == -1)
        stbuf.st_mtime = 0;

    for(i=0;i<numfiles;i++)
    {
        if (marked4extraction[i] == 0) continue;

        fileleng[i] = fileoffs[i+1]-fileoffs[i];

        if ((fil2 = Bopen(filelist[i],BO_BINARY|BO_TRUNC|BO_CREAT|BO_WRONLY,BS_IREAD|BS_IWRITE)) == -1)
        {
            Bprintf("Error: Could not write to %s\n",filelist[i]);
            continue;
        }
        Bprintf("Extracting %s...\n",filelist[i]);
        Blseek(fil,fileoffs[i]+((numfiles+1)<<4),SEEK_SET);
        for(j=0;j<fileleng[i];j+=65536)
        {
            k = min(fileleng[i]-j,65536);
            Bread(fil,buf,k);
            if (Bwrite(fil2,buf,k) < k)
            {
                Bprintf("Write error (drive full?)\n");
                Bclose(fil2);
                Bclose(fil);
                return(0);
            }
        }
        Bclose(fil2);

        if (stbuf.st_mtime != 0)
        {
            struct utimbuf times;

            times.modtime = stbuf.st_mtime;
            times.actime = Btime();

            Butime(filelist[i],&times);
        }
    }
    Bclose(fil);

    return 0;
}


code:
// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
// Ken Silverman's official web site: "http://www.advsys.net/ken"
// See the included license file "BUILDLIC.TXT" for license info.
//
// This file has been modified from Ken Silverman's original release
// by Jonathon Fowler (jf@jonof.id.au)

#include "compat.h"
#include "kplib.h"

// Glibc doesn't provide this function, so for the sake of less ugliess
// for all platforms, here's a replacement just for this program.
static void jstrupr(char *s) { while (*s) { *s = Btoupper(*s); s++; } }

#define MAXFILES 4096

static char buf[65536];        // These limits should be abolished one day

static int numfiles;
static char filespec[MAXFILES][128], filelist[MAXFILES][16];
static int fileleng[MAXFILES];

static char const * matchstr = "*.*";
int checkmatch(const struct Bdirent *a)
{
    if (a->mode & BS_IFDIR) return 0;    // is a directory
    if (a->namlen > 12) return 0;    // name too long
    return Bwildmatch(a->name, matchstr);
}

int filesize(const char *path, const char *name)
{
    char p[BMAX_PATH];
    struct stat st;

    strcpy(p, path);
    strcat(p, "/");
    strcat(p, name);

    if (!stat(p, &st)) return st.st_size;
    return 0;
}

void findfiles(const char *dafilespec)
{
    struct Bdirent *name;
    int daspeclen;
    char daspec[128];
    char const * dir;
    BDIR *di;

    strcpy(daspec,dafilespec);
    daspeclen=strlen(daspec);
    while ((daspec[daspeclen] != '\\') && (daspec[daspeclen] != '/') && (daspeclen > 0)) daspeclen--;
    if (daspeclen > 0) {
        daspec[daspeclen]=0;
        dir = daspec;
        matchstr = &daspec[daspeclen+1];
    } else {
        dir = ".";
        matchstr = daspec;
    }

    di = Bopendir(dir);
    if (!di) return;

    while ((name = Breaddir(di))) {
        if (!checkmatch(name)) continue;

        strcpy(&filelist[numfiles][0],name->name);
        jstrupr(&filelist[numfiles][0]);
        fileleng[numfiles] = name->size;
        filelist[numfiles][12] = (char)(fileleng[numfiles]&255);
        filelist[numfiles][13] = (char)((fileleng[numfiles]>>8)&255);
        filelist[numfiles][14] = (char)((fileleng[numfiles]>>16)&255);
        filelist[numfiles][15] = (char)((fileleng[numfiles]>>24)&255);

        strcpy(filespec[numfiles],dir);
        strcat(filespec[numfiles], "/");
        strcat(filespec[numfiles],name->name);

        numfiles++;
        if (numfiles > MAXFILES)
        {
            Bprintf("FATAL ERROR: TOO MANY FILES SELECTED! (MAX is 4096)\n");
            exit(0);
        }
    }

    Bclosedir(di);
}

int main(int argc, char **argv)
{
    int i, j, k, l, fil, fil2;

    if (argc < 3)
    {
        Bprintf("KGROUP <grouped file><@file or filespec...>               by Kenneth Silverman\n");
        Bprintf("   This program collects many files into 1 big uncompressed file called a\n");
        Bprintf("   group file\n");
        Bprintf("   Ex: kgroup stuff.dat *.art *.map *.k?? palette.dat tables.dat\n");
        Bprintf("      (stuff.dat is the group file, the rest are the files to add)\n");
        exit(0);
    }

    numfiles = 0;
    for(i=argc-1;i>1;i--)
    {
        if (argv[i][0] == '@')
        {
            if ((fil = Bopen(&argv[i][1],BO_BINARY|BO_RDONLY,BS_IREAD)) != -1)
            {
                l = Bread(fil,buf,65536);
                j = 0;
                while ((j < l) && (buf[j] <= 32)) j++;
                while (j < l)
                {
                    k = j;
                    while ((k < l) && (buf[k] > 32)) k++;

                    buf[k] = 0;
                    findfiles(&buf[j]);
                    j = k+1;

                    while ((j < l) && (buf[j] <= 32)) j++;
                }
                Bclose(fil);
            }
        }
        else
            findfiles(argv[i]);
    }

    if ((fil = Bopen(argv[1],BO_BINARY|BO_TRUNC|BO_CREAT|BO_WRONLY,BS_IREAD|BS_IWRITE)) == -1)
    {
        Bprintf("Error: %s could not be opened\n",argv[1]);
        exit(0);
    }
    Bwrite(fil,"KenSilverman",12);
    Bwrite(fil,&numfiles,4);
    Bwrite(fil,filelist,numfiles<<4);

    for(i=0;i<numfiles;i++)
    {
        Bprintf("Adding %s...\n",filespec[i]);
        if ((fil2 = Bopen(filespec[i],BO_BINARY|BO_RDONLY,BS_IREAD)) == -1)
        {
            Bprintf("Error: %s not found\n",filespec[i]);
            Bclose(fil);
            return(0);
        }
        for(j=0;j<fileleng[i];j+=65536)
        {
            k = min(fileleng[i]-j,65536);
            Bread(fil2,buf,k);
            if (Bwrite(fil,buf,k) < k)
            {
                Bclose(fil2);
                Bclose(fil);
                Bprintf("OUT OF HD SPACE!\n");
                return(0);
            }
        }
        Bclose(fil2);
    }
    Bclose(fil);
    Bprintf("Saved to %s.\n",argv[1]);

    return 0;
}


code:
#include "compat.h"

typedef struct { float x, y, z; } point3d;

typedef struct
{  int id, vers, skinxsiz, skinysiz, framebytes; // id:"IPD2", vers:8
    int numskins, numverts, numuv, numtris, numglcmds, numframes;
    int ofsskins, ofsuv, ofstris, ofsframes, ofsglcmds, ofseof; // ofsskins: skin names (64 bytes each)
} md2typ;

typedef struct { point3d mul, add; } frametyp;

int main (const int argc, const char **argv)
{
    BFILE *fil;
    int i, leng;
    char *fbuf;
    float zoffset = 0.0f;
    md2typ *head;
    frametyp *fptr;

    if (argc != 4)
    {
        Bputs("KMD2TOOL <MD2 in file> <MD2 out file> <z offset>              by Ken Silverman");
        return(1);
    }
    if (!Bstrcasecmp(argv[1],argv[2]))
    {
        Bputs("Error: input and output filenames cannot be the same");
        return(2);
    }

    zoffset = Batof(argv[3]);
    if (0.0f == zoffset)
    {
        Bputs("Error: offset of zero");
        return(3);
    }

    fil = Bfopen(argv[1],"rb");
    if (!fil)
    {
        Bputs("Error: could not open input MD2");
        return(4);
    }

    Bfseek(fil, 0, SEEK_END);
    leng = Bftell(fil);
    Bfseek(fil, 0, SEEK_SET);

    fbuf = (char *)Bmalloc(leng * sizeof(char));
    if (!fbuf)
    {
        Bputs("Error: Could not allocate buffer");
        return(5);
    }

    Bfread(fbuf,leng,1,fil);
    Bfclose(fil);

    head = (md2typ *)fbuf;
    if ((head->id != 0x32504449) && (head->vers != 8)) // "IDP2"
    {
        Bfree(fbuf);
        Bputs("Error: input is not an MD2 file");
        return(6);
    }

    for(i=0; i<head->numframes; ++i)
    {
        fptr = (frametyp *)&fbuf[head->ofsframes+head->framebytes*i];
        Bprintf("frame %2d scale:%f,%f,%f offs:%f,%f,%f\n",i,fptr->mul.x,fptr->mul.y,fptr->mul.z,fptr->add.x,fptr->add.y,fptr->add.z);
        fptr->add.z += zoffset;
    }

    fil = Bfopen(argv[2],"wb");
    if (!fil)
    {
        Bputs("Error: could not open output file for writing");
        return(7);
    }
    Bfwrite(fbuf,leng,1,fil);
    Bfclose(fil);

    Bfree(fbuf);

    return(0);
}


code:
// gcc b.c -Lc:/mingw32/lib -lmingw32 -lSDLmain -lSDL

#include "compat.h"
#include "sdl_inc.h"

#include "sdlkeytrans.cpp"

#undef main

int main(void)
{
    unsigned int i;

    buildkeytranslationtable();

    for (i = 0; i < sizeof(keytranslation); i++) {
        if (i>0) printf(", ");
        if (i%8 == 7) printf("\n");
        printf("%d", keytranslation[i]);
    }

    return 0;
}


code:
#include "compat.h"

#define PI 3.141592653589793

typedef struct { float x, y; } point2d;
typedef struct { float x, y, z; } point3d;
typedef struct { float x, y, z; int32_t n; } kgln_t;
typedef struct { int32_t w, s; } vertlist_t;
typedef struct { float x, y; int32_t n, ns, nw; } wall_t;
typedef struct { float z[2]; point2d grad[2]; wall_t *wall; int32_t n; } sect_t;
static int32_t numsects;
static sect_t *sec;

    //Build1 format variables:
typedef struct { int16_t picnum, heinum; int8_t shade; uint8_t pal, xpanning, ypanning; } build7surf_t;
typedef struct
{
    int16_t wallptr, wallnum;
    int32_t z[2]; int16_t stat[2]; build7surf_t surf[2];
    uint8_t visibility, filler;
    int16_t lotag, hitag, extra;
} build7sect_t;
typedef struct
{
    int32_t x, y;
    int16_t point2, nextwall, nextsect, cstat, picnum, overpicnum;
    int8_t shade;
    uint8_t pal, xrepeat, yrepeat, xpanning, ypanning;
    int16_t lotag, hitag, extra;
} build7wall_t;
static build7sect_t b7sec;
static build7wall_t b7wal;

static void checknextwalls (void)
{
    float x0, y0, x1, y1;
    int32_t s0, w0, w0n, s1, w1, w1n;

        //Clear all nextsect/nextwalls
    for (s0=0;s0<numsects;s0++)
        for (w0=0;w0<sec[s0].n;w0++) sec[s0].wall[w0].ns = sec[s0].wall[w0].nw = -1;

    for (s1=1;s1<numsects;s1++)
        for (w1=0;w1<sec[s1].n;w1++)
        {
            x0 = sec[s1].wall[w1].x;  y0 = sec[s1].wall[w1].y; w1n = sec[s1].wall[w1].n+w1;
            x1 = sec[s1].wall[w1n].x; y1 = sec[s1].wall[w1n].y;
            for (s0=0;s0<s1;s0++)
                for (w0=0;w0<sec[s0].n;w0++)
                    if ((sec[s0].wall[w0].x == x1) && (sec[s0].wall[w0].y == y1))
                    {
                        w0n = sec[s0].wall[w0].n+w0;
                        if ((sec[s0].wall[w0n].x == x0) && (sec[s0].wall[w0n].y == y0))
                        {
                            sec[s1].wall[w1].ns = s0;
                            sec[s1].wall[w1].nw = w0;
                            sec[s0].wall[w0].ns = s1;
                            sec[s0].wall[w0].nw = w1;
                            goto cnw_break2;
                        }
                    }
cnw_break2:;
        }
}

static void shellsrt (float *a, int32_t n)
{
    float t;
    int32_t i, j, g;

    for (g=(n>>1);g;g>>=1)
        for (i=0;i<n-g;i++)
            for (j=i;(j>=0)&&(a[j]>a[j+g]);j-=g)
                { t = a[j]; a[j] = a[j+g]; a[j+g] = t; }
}

static float getslopez (sect_t *s, int32_t i, float x, float y)
{
    wall_t *wal = s->wall;
    return (wal[0].x-x)*s->grad[i].x + (wal[0].y-y)*s->grad[i].y + s->z[i];
}

typedef struct { float x[4], y[2]; wall_t * pwal[2]; } zoid_t;
static int32_t sect2trap (wall_t *wal, int32_t n, zoid_t **retzoids, int32_t *retnzoids)
{
    zoid_t *zoids = 0;
    float f, x0, y0, x1, y1, sy0, sy1, cury, *secy = NULL, *trapx0 = NULL, *trapx1 = NULL;
    int32_t i, j, g, s, secn, ntrap, tot, zoidalloc;
    wall_t * k;
    wall_t ** pwal = NULL;

    (*retzoids) = 0; (*retnzoids) = 0; if (n < 3) return 0;

    secy = (float *)malloc(n*sizeof(secy[0])); if (!secy) goto badret;
    trapx0 = (float *)malloc(n*sizeof(trapx0[0])); if (!trapx0) goto badret;
    trapx1 = (float *)malloc(n*sizeof(trapx1[0])); if (!trapx1) goto badret;
    pwal = (wall_t **)malloc(n*sizeof(pwal[0])); if (!pwal) goto badret;

    for (i=n-1;i>=0;i--) secy[i] = wal[i].y;
    shellsrt(secy,n);
    for (i=0,secn=0,cury=-1e32f;i<n;i++) //remove dups
        if (secy[i] > cury) { secy[secn++] = cury = secy[i]; }

    zoidalloc = secn*2; //just a guess (not guaranteed to fit)
    zoids = (zoid_t *)malloc(zoidalloc*sizeof(zoid_t)); if (!zoids) goto badret;

    tot = 0;
    for (s=0;s<secn-1;s++)
    {
        sy0 = secy[s]; sy1 = secy[s+1]; ntrap = 0;
        for (i=0;i<n;i++) //FIX:optimize
        {
            x0 = wal[i].x; y0 = wal[i].y; j = wal[i].n+i;
            x1 = wal[j].x; y1 = wal[j].y;
            if (y0 > y1)
            {
                f = x0; x0 = x1; x1 = f;
                f = y0; y0 = y1; y1 = f;
            }
            if ((y0 >= sy1) || (y1 <= sy0)) continue;
            if (y0 < sy0) x0 = (sy0-wal[i].y)*(wal[j].x-wal[i].x)/(wal[j].y-wal[i].y) + wal[i].x;
            if (y1 > sy1) x1 = (sy1-wal[i].y)*(wal[j].x-wal[i].x)/(wal[j].y-wal[i].y) + wal[i].x;
            trapx0[ntrap] = x0; trapx1[ntrap] = x1; pwal[ntrap] = &wal[i]; ntrap++;
        }
        for (g=(ntrap>>1);g;g>>=1)
            for (i=0;i<ntrap-g;i++)
                for (j=i;j>=0;j-=g)
                {
                    if (trapx0[j]+trapx1[j] <= trapx0[j+g]+trapx1[j+g]) break;
                    f = trapx0[j]; trapx0[j] = trapx0[j+g]; trapx0[j+g] = f;
                    f = trapx1[j]; trapx1[j] = trapx1[j+g]; trapx1[j+g] = f;
                    k =    pwal[j];    pwal[j] =    pwal[j+g];    pwal[j+g] = k;
                }

        if (tot+ntrap > zoidalloc)
        {
            zoidalloc <<= 1; if (tot+ntrap > zoidalloc) zoidalloc = tot+ntrap;
            zoids = (zoid_t *)realloc(zoids,zoidalloc*sizeof(zoid_t)); if (!zoids) goto badret;
        }
        for (i=0;i<ntrap;i=j+1)
        {
            j = i+1; if ((trapx0[i+1] <= trapx0[i]) && (trapx1[i+1] <= trapx1[i])) continue;
            while ((j+2 < ntrap) && (trapx0[j+1] <= trapx0[j]) && (trapx1[j+1] <= trapx1[j])) j += 2;
            zoids[tot].x[0] = trapx0[i]; zoids[tot].x[1] = trapx0[j]; zoids[tot].y[0] = sy0;
            zoids[tot].x[3] = trapx1[i]; zoids[tot].x[2] = trapx1[j]; zoids[tot].y[1] = sy1;
            zoids[tot].pwal[0] = pwal[i]; zoids[tot].pwal[1] = pwal[j];
            tot++;
        }
    }
    (*retzoids) = zoids; (*retnzoids) = tot; return 1;
badret:;
    free(secy);
    free(trapx0);
    free(trapx1);
    free(pwal);
    free(zoids);
    return 0;
}

static int32_t getwalls (int32_t s, int32_t w, vertlist_t *ver, int32_t maxverts)
{
    vertlist_t tver;
    wall_t *wal, *wal2;
    float fx, fy;
    int32_t i, j, k, bs, bw, nw, vn;

    wal = sec[s].wall; bs = wal[w].ns;
    if ((unsigned)bs >= (unsigned)numsects) return 0;

    vn = 0; nw = wal[w].n+w; bw = wal[w].nw;
    do
    {
        wal2 = sec[bs].wall; i = wal2[bw].n+bw; //Make sure it's an opposite wall
        if ((wal[w].x == wal2[i].x) && (wal[nw].x == wal2[bw].x) &&
             (wal[w].y == wal2[i].y) && (wal[nw].y == wal2[bw].y))
            { if (vn < maxverts) { ver[vn].s = bs; ver[vn].w = bw; vn++; } }
        bs = wal2[bw].ns;
        bw = wal2[bw].nw;
    } while (bs != s);

        //Sort next sects by order of height in middle of wall (crap sort)
    fx = (wal[w].x+wal[nw].x)*.5f;
    fy = (wal[w].y+wal[nw].y)*.5f;
    for (k=1;k<vn;k++)
        for (j=0;j<k;j++)
            if (getslopez(&sec[ver[j].s],0,fx,fy) + getslopez(&sec[ver[j].s],1,fx,fy) >
                 getslopez(&sec[ver[k].s],0,fx,fy) + getslopez(&sec[ver[k].s],1,fx,fy))
                { tver = ver[j]; ver[j] = ver[k]; ver[k] = tver; }
    return(vn);
}

static int32_t wallclip (kgln_t *pol, kgln_t *npol)
{
    float f, dz0, dz1;

    dz0 = pol[3].z-pol[0].z; dz1 = pol[2].z-pol[1].z;
    if (dz0 > 0.0) //do not include null case for rendering
    {
        npol[0] = pol[0];
        if (dz1 > 0.0) //do not include null case for rendering
        {
            npol[1] = pol[1];
            npol[2] = pol[2];
            npol[3] = pol[3];
            npol[0].n = npol[1].n = npol[2].n = 1; npol[3].n = -3;
            return 4;
        }
        else
        {
            f = dz0/(dz0-dz1);
            npol[1].x = (pol[1].x-pol[0].x)*f + pol[0].x;
            npol[1].y = (pol[1].y-pol[0].y)*f + pol[0].y;
            npol[1].z = (pol[1].z-pol[0].z)*f + pol[0].z;
            npol[2] = pol[3];
            npol[0].n = npol[1].n = 1; npol[2].n = -2;
            return 3;
        }
    }
    if (dz1 <= 0.0) return 0; //do not include null case for rendering
    f = dz0/(dz0-dz1);
    npol[0].x = (pol[1].x-pol[0].x)*f + pol[0].x;
    npol[0].y = (pol[1].y-pol[0].y)*f + pol[0].y;
    npol[0].z = (pol[1].z-pol[0].z)*f + pol[0].z;
    npol[1] = pol[1];
    npol[2] = pol[2];
    npol[0].n = npol[1].n = 1; npol[2].n = -2;
    return 3;
}

    //    //STL binary format:
    //char filler[80];
    //uint32_t numtris;
    //for (i=0;i<numtris;i++)
    //{
    //    point3d norm, v[3]; //vertices are CCW and must be + coords
    //    int16_t filler;
    //}
static void saveasstl (char const * filnam)
{
    #define MAXVERTS 256 //WARNING:not dynamic
    vertlist_t verts[MAXVERTS];
    kgln_t pol[4], npol[4];
    point3d fp[3], fp2;
    point2d *grad;
    wall_t *wal;
    zoid_t *zoids;
    FILE *fil;
    float f, fz;
    int32_t i, j, k, n, w, s, nw, wn, vn, s0, cf0, s1, cf1, isflor, nzoids;
    int32_t numtris;
    char tbuf[80];

    fil = fopen(filnam,"wb"); if (!fil) return;
    memset(tbuf,0,80);
    fwrite(tbuf,80,1,fil); //header ignored in STL
    numtris = 0;
    fwrite(&numtris,4,1,fil); //dummy write

    for (s=0;s<numsects;s++)
    {
            //draw sector filled
        for (isflor=0;isflor<2;isflor++)
        {
            wal = sec[s].wall; fz = sec[s].z[isflor]; grad = &sec[s].grad[isflor]; n = sec[s].n;

            if (!sect2trap(wal,n,&zoids,&nzoids)) continue;

            for (i=0;i<nzoids;i++)
            {
                for (j=0,n=0;j<4;j++)
                {
                    pol[n].x = zoids[i].x[j];
                    pol[n].y = zoids[i].y[j>>1];
                    if ((!n) || (pol[n].x != pol[n-1].x) || (pol[n].y != pol[n-1].y))
                    {
                        pol[n].z = (wal[0].x-pol[n].x)*grad->x + (wal[0].y-pol[n].y)*grad->y + fz;
                        pol[n].n = 1; n++;
                    }
                }
                if (n < 3) continue;
                pol[n-1].n = 1-n;

                fp[0].x = pol[0].x; fp[0].y = pol[0].y; fp[0].z = pol[0].z;
                for (j=2;j<n;j++)
                {
                    k = j-isflor;    fp[1].x = pol[k].x; fp[1].y = pol[k].y; fp[1].z = pol[k].z;
                    k = j-1+isflor; fp[2].x = pol[k].x; fp[2].y = pol[k].y; fp[2].z = pol[k].z;
                        //fp2 = unit norm
                    fp2.x = (fp[1].y-fp[0].y)*(fp[2].z-fp[0].z) - (fp[1].z-fp[0].z)*(fp[2].y-fp[0].y);
                    fp2.y = (fp[1].z-fp[0].z)*(fp[2].x-fp[0].x) - (fp[1].x-fp[0].x)*(fp[2].z-fp[0].z);
                    fp2.z = (fp[1].x-fp[0].x)*(fp[2].y-fp[0].y) - (fp[1].y-fp[0].y)*(fp[2].x-fp[0].x);
                    f = fp2.x*fp2.x + fp2.y*fp2.y + fp2.z*fp2.z; if (f > 0.f) f = -1.f/sqrtf(f);
                    fp2.x *= f; fp2.y *= f; fp2.z *= f; fwrite(&fp2,4*3,1,fil);
                    fwrite(fp,4*3*3,1,fil); fwrite(tbuf,2,1,fil); //2 bytes of filler
                    numtris++;
                }
            }
            free(zoids);
        }

        wal = sec[s].wall; wn = sec[s].n;
        for (w=0;w<wn;w++)
        {
            nw = wal[w].n+w; vn = getwalls(s,w,verts,MAXVERTS);
            pol[0].x = wal[ w].x; pol[0].y = wal[ w].y; pol[0].n = 1;
            pol[1].x = wal[nw].x; pol[1].y = wal[nw].y; pol[1].n = 1;
            pol[2].x = wal[nw].x; pol[2].y = wal[nw].y; pol[2].n = 1;
            pol[3].x = wal[ w].x; pol[3].y = wal[ w].y; pol[3].n =-3;
            for (k=0;k<=vn;k++) //Warning: do not reverse for loop!
            {
                if (k >  0) { s0 = verts[k-1].s; cf0 = 1; } else { s0 = s; cf0 = 0; }
                if (k < vn) { s1 = verts[k  ].s; cf1 = 0; } else { s1 = s; cf1 = 1; }

                pol[0].z = getslopez(&sec[s0],cf0,pol[0].x,pol[0].y);
                pol[1].z = getslopez(&sec[s0],cf0,pol[1].x,pol[1].y);
                pol[2].z = getslopez(&sec[s1],cf1,pol[2].x,pol[2].y);
                pol[3].z = getslopez(&sec[s1],cf1,pol[3].x,pol[3].y);
                i = wallclip(pol,npol); if (!i) continue;

                fp[0].x = npol[0].x; fp[0].y = npol[0].y; fp[0].z = npol[0].z;
                for (j=2;j<i;j++)
                {
                    fp[1].x = npol[j-1].x; fp[1].y = npol[j-1].y; fp[1].z = npol[j-1].z;
                    fp[2].x = npol[j  ].x; fp[2].y = npol[j  ].y; fp[2].z = npol[j  ].z;
                        //fp2 = unit norm
                    fp2.x = (fp[1].y-fp[0].y)*(fp[2].z-fp[0].z) - (fp[1].z-fp[0].z)*(fp[2].y-fp[0].y);
                    fp2.y = (fp[1].z-fp[0].z)*(fp[2].x-fp[0].x) - (fp[1].x-fp[0].x)*(fp[2].z-fp[0].z);
                    fp2.z = (fp[1].x-fp[0].x)*(fp[2].y-fp[0].y) - (fp[1].y-fp[0].y)*(fp[2].x-fp[0].x);
                    f = fp2.x*fp2.x + fp2.y*fp2.y + fp2.z*fp2.z; if (f > 0.f) f = -1.f/sqrtf(f);
                    fp2.x *= f; fp2.y *= f; fp2.z *= f; fwrite(&fp2,4*3,1,fil);
                    fwrite(fp,4*3*3,1,fil); fwrite(tbuf,2,1,fil); //2 bytes of filler
                    numtris++;
                }
            }
        }
    }

    i = ftell(fil);
    fseek(fil,80,SEEK_SET); fwrite(&numtris,4,1,fil);
    fseek(fil,i,SEEK_SET);
    fclose(fil);
}

static int32_t loadmap (char *filnam)
{
    float f, fx, fy;
    int32_t i, j, k;
    int16_t s;
    FILE *fil;

    fil = fopen(filnam,"rb"); if (!fil) return 0;
    fread(&i,4,1,fil); if (i != 0x00000007) return 0; //not Build1 .MAP format 7
    fseek(fil,20,SEEK_SET);

    fread(&s,2,1,fil); numsects = (int32_t)s;
    sec = (sect_t *)malloc(numsects*sizeof(sect_t));
    memset(sec,0,numsects*sizeof(sect_t));
    for (i=0;i<numsects;i++)
    {
        fread(&b7sec,sizeof(b7sec),1,fil);
        sec[i].n = b7sec.wallnum;
        sec[i].wall = (wall_t *)realloc(sec[i].wall,sec[i].n*sizeof(wall_t));
        memset(sec[i].wall,0L,sec[i].n*sizeof(wall_t));
        for (j=0;j<2;j++)
        {
            sec[i].z[j] = ((float)b7sec.z[j])*(1.f/(512.f*16.f));
            sec[i].grad[j].x = sec[i].grad[j].y = 0;
            if (b7sec.stat[j]&2) //Enable slopes flag
                sec[i].grad[j].y = ((float)b7sec.surf[j].heinum)*(1.f/4096.f);
        }
    }

    fread(&s,2,1,fil); //numwalls
    for (i=k=0;i<numsects;i++)
    {
        for (j=0;j<sec[i].n;j++,k++)
        {
            fread(&b7wal,sizeof(b7wal),1,fil);
            sec[i].wall[j].x = ((float)b7wal.x)*(1.f/512.f);
            sec[i].wall[j].y = ((float)b7wal.y)*(1.f/512.f);
            sec[i].wall[j].n = b7wal.point2-k;
        }

        fx = sec[i].wall[1].y-sec[i].wall[0].y;
        fy = sec[i].wall[0].x-sec[i].wall[1].x;
        f = fx*fx + fy*fy; if (f > 0.f) f = 1.f/sqrtf(f); fx *= f; fy *= f;
        for (j=0;j<2;j++)
        {
            sec[i].grad[j].x = fx*sec[i].grad[j].y;
            sec[i].grad[j].y = fy*sec[i].grad[j].y;
        }
    }

    checknextwalls();
    fclose(fil);
    return 1;
}

int main (int argc, char **argv)
{
    if (argc != 3)
    {
        printf("map2stl [in:Build .MAP (v7)] [out:STL file]         by Ken Silverman (05/15/2009)");
        return 1;
    }
    if (!loadmap(argv[1]))
    {
        printf("error loading map\n");
        return 2;
    }
    saveasstl(argv[2]);
    return 0;
}


code:
#include "compat.h"
#include "build.h"
#include "glad/glad.h"
#include "mdsprite.h"

static md2head_t head;

static void quit(int32_t status)
{
    exit(status);
}

static md2model_t *md2load(int *fd, const char *filename, int32_t ronly)
{
    md2model_t *m;
    int fil;

    fil = Bopen(filename, ronly?BO_RDONLY:BO_RDWR);
    if (fil<0)
    {
        Bfprintf(stderr, "Couldn't open `%s': %s\n", filename, strerror(errno));
        quit(2);
    }

    m = (md2model_t *)Bcalloc(1,sizeof(md2model_t)); if (!m) quit(1);
    m->mdnum = 2; m->scale = .01f;

    Bread(fil,(char *)&head,sizeof(md2head_t));

    head.id = B_LITTLE32(head.id);                 head.vers = B_LITTLE32(head.vers);
    head.skinxsiz = B_LITTLE32(head.skinxsiz);     head.skinysiz = B_LITTLE32(head.skinysiz);
    head.framebytes = B_LITTLE32(head.framebytes); head.numskins = B_LITTLE32(head.numskins);
    head.numverts = B_LITTLE32(head.numverts);     head.numuv = B_LITTLE32(head.numuv);
    head.numtris = B_LITTLE32(head.numtris);       head.numglcmds = B_LITTLE32(head.numglcmds);
    head.numframes = B_LITTLE32(head.numframes);   head.ofsskins = B_LITTLE32(head.ofsskins);
    head.ofsuv = B_LITTLE32(head.ofsuv);           head.ofstris = B_LITTLE32(head.ofstris);
    head.ofsframes = B_LITTLE32(head.ofsframes);   head.ofsglcmds = B_LITTLE32(head.ofsglcmds);
    head.ofseof = B_LITTLE32(head.ofseof);

    if ((head.id != 0x32504449) || (head.vers != 8))
    {
        Bfprintf(stderr, "File `%s' is not an md2 file.\n", filename);
        quit(3);
    } //"IDP2"

    m->numskins = head.numskins;
    m->numframes = head.numframes;
    m->numverts = head.numverts;
    m->numglcmds = head.numglcmds;
    m->framebytes = head.framebytes;

    m->frames = (char *)Bmalloc(m->numframes*m->framebytes); if (!m->frames) quit(1);
    m->tris = (md2tri_t *)Bmalloc(head.numtris*sizeof(md2tri_t)); if (!m->tris) quit(1);
    m->uv = (md2uv_t *)Bmalloc(head.numuv*sizeof(md2uv_t)); if (!m->uv) quit(1);

    Blseek(fil,head.ofsframes,SEEK_SET);
    if (Bread(fil,(char *)m->frames,m->numframes*m->framebytes) != m->numframes*m->framebytes)
        quit(1);

    Blseek(fil,head.ofstris,SEEK_SET);
    if (Bread(fil,(char *)m->tris,head.numtris*sizeof(md2tri_t)) != (int32_t)(head.numtris*sizeof(md2tri_t)))
        quit(1);

    Blseek(fil,head.ofsuv,SEEK_SET);
    if (Bread(fil,(char *)m->uv,head.numuv*sizeof(md2uv_t)) != (int32_t)(head.numuv*sizeof(md2uv_t)))
        quit(1);

#if B_BIG_ENDIAN != 0
    {
        char *f = (char *)m->frames;
        int32_t *l,i,j;
        md2frame_t *fr;

        for (i = m->numframes-1; i>=0; i--)
        {
            fr = (md2frame_t *)f;
            l = (int32_t *)&fr->mul;
            for (j=5; j>=0; j--) l[j] = B_LITTLE32(l[j]);
            f += m->framebytes;
        }

        for (i = head.numtris-1; i>=0; i--)
        {
            m->tris[i].v[0] = B_LITTLE16(m->tris[i].v[0]);
            m->tris[i].v[1] = B_LITTLE16(m->tris[i].v[1]);
            m->tris[i].v[2] = B_LITTLE16(m->tris[i].v[2]);
            m->tris[i].u[0] = B_LITTLE16(m->tris[i].u[0]);
            m->tris[i].u[1] = B_LITTLE16(m->tris[i].u[1]);
            m->tris[i].u[2] = B_LITTLE16(m->tris[i].u[2]);
        }
        for (i = head.numuv-1; i>=0; i--)
        {
            m->uv[i].u = B_LITTLE16(m->uv[i].u);
            m->uv[i].v = B_LITTLE16(m->uv[i].v);
        }
    }
#endif

    *fd = fil;
    return(m);
}

static void usage_and_quit()
{
    Bfprintf(stderr,
            "Usage:\n"
            "   md2tool <modelfile>.md2:  display info about model\n"
            "   md2tool -minmax <minx>,<miny>,<minz>:<maxx>,<maxy>,<maxz> <modelfile>.md2:\n"
            "      modify `scale' and `translate' fields of MD2 (in-place) to produce given bounds\n"
        );
    quit(1);
}

int main(int argc, char **argv)
{
    char *fn=NULL, *cp;
    int32_t fd=-1, i, j;

    int32_t doinfo=1;

    // md2 mul[x,y,z], add[x,y,z]
    float mx,my,mz, ax,ay,az;

    // desired model bounds
    float dminx=0,dminy=0,dminz=0, dmaxx=1,dmaxy=1,dmaxz=1;

    // md2 uint8-coordinate bounds
    uint8_t maxv[3]={0,0,0};
    uint8_t minv[3]={255,255,255};

    md2frame_t *fr;
    uint8_t *vp;

    md2model_t *m;

    if (argc<=1)
        usage_and_quit();

    for (i=1; i<argc; i++)
    {
        cp = argv[i];

        if (cp[0]=='-')
        {
            if (!strcmp(cp, "-minmax"))
            {
                doinfo=0;
                if (i+1 >= argc)
                    usage_and_quit();
                if (Bsscanf(argv[i+1], "%f,%f,%f:%f,%f,%f", &dminx,&dminy,&dminz, &dmaxx,&dmaxy,&dmaxz)!=6)
                    usage_and_quit();
                i++;
            }
            else
            {
                Bfprintf(stderr, "unrecognized option `%s'\n", cp);
                quit(2);
            }
        }
        else
            fn = cp;
    }

    if (!fn)
        usage_and_quit();

    m = md2load(&fd, fn, doinfo);

    fr = (md2frame_t *)m->frames;
    mx=fr->mul.x; my=fr->mul.y; mz=fr->mul.z;
    ax=fr->add.x; ay=fr->add.y; az=fr->add.z;

    for (i=0, vp=fr->verts->v; i<m->numverts; i++, vp+=sizeof(md2vert_t))
    {
        for (j=0; j<3; j++)
        {
            maxv[j] = max(maxv[j], vp[j]);
            minv[j] = min(minv[j], vp[j]);
        }
    }

    if (doinfo)
    {
        Bprintf("------ %s ------\n", fn);
        Bprintf("numframes: %d\n", m->numframes);
        Bprintf("numverts: %d\n", m->numverts);
        Bprintf("numtris: %d\n", head.numtris);
        Bprintf("\n");
        Bprintf("ofsframes: %x\n", head.ofsframes);
        Bprintf("framebytes: %d\n", head.framebytes);
//        Bprintf("framebytes: %d, calculated=%d\n", head.framebytes, sizeof(md2frame_t)+(m->numverts-1)*sizeof(md2vert_t));
        Bprintf("\n");

        Bprintf("mul=%f %f %f\n", mx, my, mz);
        Bprintf("add=%f %f %f\n", ax, ay, az);

        Bprintf("min xyz (s+t) = %f %f %f\n", minv[0]*mx+ax, minv[1]*my+ay, minv[2]*mz+az);
        Bprintf("max xyz (s+t) = %f %f %f\n", maxv[0]*mx+ax, maxv[1]*my+ay, maxv[2]*mz+az);

        Bprintf("\n");
    }
    else
    {
        if (maxv[0]-minv[0]>0) mx = (dmaxx-dminx)/(maxv[0]-minv[0]); else mx=0;
        if (maxv[1]-minv[1]>0) my = (dmaxy-dminy)/(maxv[1]-minv[1]); else my=0;
        if (maxv[2]-minv[2]>0) mz = (dmaxz-dminz)/(maxv[2]-minv[2]); else mz=0;

        if (mx==0||my==0||mz==0)
        {
            Bfprintf(stderr, "max[x,y,z]-min[x,y,z] must each be grater 0!\n");
            quit(2);
        }

        ax = dmaxx-maxv[0]*mx;
        ay = dmaxy-maxv[1]*my;
        az = dmaxz-maxv[2]*mz;

#define ISNAN(x) ((x)!=(x))
#define ISINF(x) ((x!=0)&&(x/2==x))

        if (ISNAN(mx)||ISNAN(my)||ISNAN(mz)||ISNAN(ax)||ISNAN(ay)||ISNAN(az)||
            ISINF(mx)||ISINF(my)||ISINF(mz)||ISINF(ax)||ISINF(ay)||ISINF(az))
        {
            Bfprintf(stderr, "Calculation resulted in NaN or Inf.\n");
            quit(2);
        }

        Blseek(fd,head.ofsframes,SEEK_SET);
        if (Bwrite(fd, &mx, sizeof(mx))!=sizeof(mx)) { perror("write"); quit(3); }
        if (Bwrite(fd, &my, sizeof(my))!=sizeof(my)) { perror("write"); quit(3); }
        if (Bwrite(fd, &mz, sizeof(mz))!=sizeof(mz)) { perror("write"); quit(3); }
        if (Bwrite(fd, &ax, sizeof(ax))!=sizeof(ax)) { perror("write"); quit(3); }
        if (Bwrite(fd, &ay, sizeof(ay))!=sizeof(ay)) { perror("write"); quit(3); }
        if (Bwrite(fd, &az, sizeof(az))!=sizeof(az)) { perror("write"); quit(3); }
        Bclose(fd);

        Bprintf("wrote scale and translate of `%s'.\n", fn);
    }

    return 0;
}