code:
// Here lies the slow as shit renderer!

#ifndef polymer_h_
# define polymer_h_

# include "baselayer.h"
# include "build.h"
# include "compat.h"
# include "glad/glad.h"
# include "glbuild.h"
# include "hightile.h"
# include "mdsprite.h"
# include "osd.h"
# include "polymost.h"
# include "pragmas.h"

#ifdef __cplusplus
extern "C" {
#endif

#define PR_LINEAR_FOG

// CVARS
extern int32_t      pr_lighting;
extern int32_t      pr_normalmapping;
extern int32_t      pr_specularmapping;
extern int32_t      pr_shadows;
extern int32_t      pr_shadowcount;
extern int32_t      pr_shadowdetail;
extern int32_t      pr_shadowfiltering;
extern int32_t      pr_maxlightpasses;
extern int32_t      pr_maxlightpriority;
extern int32_t      pr_fov;
extern double       pr_customaspect;
extern int32_t      pr_billboardingmode;
extern int32_t      pr_verbosity;
extern int32_t      pr_wireframe;
extern int32_t      pr_buckets;
extern int32_t      pr_gpusmoothing;
extern int32_t      pr_overrideparallax;
extern float        pr_parallaxscale;
extern float        pr_parallaxbias;
extern int32_t      pr_overridespecular;
extern float        pr_specularpower;
extern float        pr_specularfactor;
extern int32_t      pr_highpalookups;
extern int32_t      pr_artmapping;
extern int32_t      pr_overridehud;
extern float        pr_hudxadd;
extern float        pr_hudyadd;
extern float        pr_hudzadd;
extern int32_t      pr_hudangadd;
extern int32_t      pr_hudfov;
extern float        pr_overridemodelscale;
extern int32_t      pr_ati_fboworkaround;
extern int32_t      pr_ati_nodepthoffset;
#ifdef __APPLE__
extern int32_t      pr_ati_textureformat_one;
#endif
extern int32_t      pr_nullrender;

extern int32_t      r_pr_maxlightpasses;
extern int32_t      r_pr_constrained;

// MATERIAL
typedef enum {
                    PR_BIT_HEADER,              // must be first
                    PR_BIT_ANIM_INTERPOLATION,
                    PR_BIT_LIGHTING_PASS,
                    PR_BIT_NORMAL_MAP,
                    PR_BIT_ART_MAP,
                    PR_BIT_DIFFUSE_MAP,
                    PR_BIT_DIFFUSE_DETAIL_MAP,
                    PR_BIT_DIFFUSE_MODULATION,
                    PR_BIT_DIFFUSE_MAP2,
                    PR_BIT_HIGHPALOOKUP_MAP,
                    PR_BIT_SPECULAR_MAP,
                    PR_BIT_SPECULAR_MATERIAL,
                    PR_BIT_MIRROR_MAP,
                    PR_BIT_FOG,
                    PR_BIT_GLOW_MAP,
                    PR_BIT_PROJECTION_MAP,
                    PR_BIT_SHADOW_MAP,
                    PR_BIT_LIGHT_MAP,
                    PR_BIT_SPOT_LIGHT,
                    PR_BIT_POINT_LIGHT,
                    PR_BIT_FOOTER,              // must be just before last
                    PR_BIT_COUNT                // must be last
}                   prbittype;

typedef struct      s_prmaterial {
    // PR_BIT_ANIM_INTERPOLATION
    GLfloat         frameprogress;
    GLfloat*        nextframedata;
    // PR_BIT_NORMAL_MAP
    GLuint          normalmap;
    GLfloat         normalbias[2];
    GLfloat*        tbn;
    // PR_BIT_ART_MAP
    GLuint          artmap;
    GLuint          basepalmap;
    GLuint          lookupmap;
    GLint           shadeoffset;
    GLfloat         visibility;
    // PR_BIT_DIFFUSE_MAP
    GLuint          diffusemap;
    GLfloat         diffusescale[2];
    // PR_BIT_HIGHPALOOKUP_MAP
    GLuint          highpalookupmap;
    // PR_BIT_DIFFUSE_DETAIL_MAP
    GLuint          detailmap;
    GLfloat         detailscale[2];
    // PR_BIT_DIFFUSE_MODULATION
    GLubyte         diffusemodulation[4];
    // PR_BIT_SPECULAR_MAP
    GLuint          specmap;
    // PR_BIT_SPECULAR_MATERIAL
    GLfloat         specmaterial[2];
    // PR_BIT_MIRROR_MAP
    GLuint          mirrormap;
    // PR_BIT_GLOW_MAP
    GLuint          glowmap;
    // PR_BIT_SHADOW_MAP
    GLboolean       mdspritespace;
}                   _prmaterial;

typedef struct      s_prrograminfo {
    GLuint          handle;
    // PR_BIT_ANIM_INTERPOLATION
    GLint           attrib_nextFrameData;
    GLint           attrib_nextFrameNormal;
    GLint           uniform_frameProgress;
    // PR_BIT_NORMAL_MAP
    GLint           attrib_T;
    GLint           attrib_B;
    GLint           attrib_N;
    GLint           uniform_eyePosition;
    GLint           uniform_normalMap;
    GLint           uniform_normalBias;
    // PR_BIT_ART_MAP
    GLuint          uniform_artMap;
    GLuint          uniform_basePalMap;
    GLuint          uniform_lookupMap;
    GLuint          uniform_shadeOffset;
    GLuint          uniform_visibility;
    // PR_BIT_DIFFUSE_MAP
    GLint           uniform_diffuseMap;
    GLint           uniform_diffuseScale;
    // PR_BIT_HIGHPALOOKUP_MAP
    GLuint          uniform_highPalookupMap;
    // PR_BIT_DIFFUSE_DETAIL_MAP
    GLint           uniform_detailMap;
    GLint           uniform_detailScale;
    // PR_BIT_SPECULAR_MAP
    GLint           uniform_specMap;
    // PR_BIT_SPECULAR_MATERIAL
    GLint           uniform_specMaterial;
    // PR_BIT_MIRROR_MAP
    GLint           uniform_mirrorMap;
#ifdef PR_LINEAR_FOG
    // PR_BIT_FOG
    GLint           uniform_linearFog;
#endif
    // PR_BIT_GLOW_MAP
    GLint           uniform_glowMap;
    // PR_BIT_PROJECTION_MAP
    GLint           uniform_shadowProjMatrix;
    // PR_BIT_SHADOW_MAP
    GLint           uniform_shadowMap;
    // PR_BIT_LIGHT_MAP
    GLint           uniform_lightMap;
    // PR_BIT_SPOT_LIGHT
    GLint           uniform_spotDir;
    GLint           uniform_spotRadius;
}                   _prprograminfo;

#define             PR_INFO_LOG_BUFFER_SIZE 8192

// Think about changing highPal[Scale|Bias] in the program bit if you change this
#define             PR_HIGHPALOOKUP_BIT_DEPTH 6
#define             PR_HIGHPALOOKUP_DIM (1 << PR_HIGHPALOOKUP_BIT_DEPTH)
#define             PR_HIGHPALOOKUP_DATA_SIZE (4 * PR_HIGHPALOOKUP_DIM * \
                                                   PR_HIGHPALOOKUP_DIM * \
                                                   PR_HIGHPALOOKUP_DIM)

typedef struct      s_prprogrambit {
    const char*           vert_def;
    const char*           vert_prog;
    const char*           frag_def;
    const char*           frag_prog;
}                   _prprogrambit;

typedef struct      s_prbucket {
    // index
    int16_t         tilenum;
    char            pal;

    _prmaterial     material;
    int32_t         invalidmaterial;

    // geom indices
    GLuint*          indices;
    uint32_t         count;
    uint32_t         buffersize;
    GLuint*          indiceoffset;

    struct s_prbucket* next;
}                   _prbucket;

#include "prlights.h"

// RENDER TARGETS
typedef struct      s_prrt {
    GLenum          target;
    GLuint          color;
    GLuint          z;
    GLuint          fbo;
    int32_t         xdim, ydim;
}                   _prrt;

// BUILD DATA

typedef struct      s_prvert {
    GLfloat         x;
    GLfloat         y;
    GLfloat         z;
    GLfloat         u;
    GLfloat         v;
    GLubyte         r;
    GLubyte         g;
    GLubyte         b;
    GLubyte         a;
}                   _prvert;

typedef struct      s_prplane {
    // geometry
    _prvert*        buffer;
    int32_t         vertcount;
    GLuint          vbo;
    uint32_t        mapvbo_vertoffset;
    _prbucket*      bucket;
    // attributes
    GLfloat         tbn[3][3];
    GLfloat         plane[4];
    _prmaterial     material;
    // elements
    GLushort*       indices;
    int32_t         indicescount;
    GLuint          ivbo;
    // lights
    int16_t         lights[PR_MAXPLANELIGHTS];
    uint16_t        lightcount;
}                   _prplane;

typedef struct      s_prsector {
    // polymer data
    GLfloat*       verts;
    _prplane        floor;
    _prplane        ceil;
    int32_t         indicescount;
    int32_t         oldindicescount;
    // stuff
    float           wallsproffset;
    float           floorsproffset;
    // build sector data
    int32_t         ceilingz, floorz;
    uint16_t        ceilingstat, floorstat;
    int16_t         ceilingpicnum, ceilingheinum;
    int8_t          ceilingshade;
    uint8_t         ceilingpal, ceilingxpanning, ceilingypanning;
    int16_t         floorpicnum, floorheinum;
    int8_t          floorshade;
    uint8_t         floorpal, floorxpanning, floorypanning;
    uint8_t         visibility;

    int16_t         floorpicnum_anim, ceilingpicnum_anim;

    struct          {
        int         empty       : 1;
        int         uptodate    : 1;
        int         invalidtex  : 1;
    }               flags;
    uint32_t        invalidid;
    uint32_t        trackedrev;
}                   _prsector;

typedef struct      s_prwall {
    _prplane        wall;
    _prplane        over;
    _prplane        mask;

    // stuff
    GLfloat*        bigportal;
    //GLfloat*        cap;
    GLuint          stuffvbo;

    // build wall data
    uint16_t        cstat;
    int16_t         picnum, overpicnum;
    int8_t          shade;
    uint8_t         pal, xrepeat, yrepeat, xpanning, ypanning;

    // nextwall data
    int16_t         nwallpicnum, nwallcstat;
    int8_t          nwallxpanning, nwallypanning;
    int8_t          nwallshade;

    int16_t         picnum_anim, overpicnum_anim;

    char            underover;
    uint32_t        invalidid;
    struct          {
        int         empty       : 1;
        int         uptodate    : 1;
        int         invalidtex  : 1;
    }               flags;
    uint32_t        trackedrev;
}                   _prwall;

typedef struct      s_prsprite {
    _prplane        plane;
    uint32_t        hash;
}                   _prsprite;

typedef struct      s_prmirror {
    _prplane        *plane;
    int16_t         sectnum;
    int16_t         wallnum;
    int8_t          rorstat;
}                   _prmirror;

typedef struct      s_prhighpalookup {
    char            *data;
    GLuint          map;
}                   _prhighpalookup;

typedef void    (*animatespritesptr)(int32_t, int32_t, int32_t, int32_t, int32_t);

typedef struct      s_pranimatespritesinfo {
    animatespritesptr animatesprites;
    int32_t         x, y, z, a, smoothratio;
}                   _pranimatespritesinfo;

typedef void    (*rorcallback)(int16_t sectnum, int16_t wallnum, int8_t rorstat, int16_t *msectnum, int32_t *gx, int32_t *gy, int32_t *gz);

// this one has to be provided by the application
extern void G_Polymer_UnInit(void);

// EXTERNAL FUNCTIONS
int32_t polymer_init(void);
void    polymer_uninit(void);
void    polymer_setaspect(int32_t);
void    polymer_glinit(void);
void    polymer_resetlights(void);
void    polymer_loadboard(void);
int32_t polymer_printtext256(int32_t xpos, int32_t ypos, int16_t col, int16_t backcol, const char *name, char fontsize);
void    polymer_fillpolygon(int32_t npoints);
void    polymer_drawrooms(int32_t daposx, int32_t daposy, int32_t daposz, fix16_t daang, int32_t dahoriz, int16_t dacursectnum);
void    polymer_drawmasks(void);
void    polymer_editorpick(void);
void    polymer_inb4rotatesprite(int16_t tilenum, char pal, int8_t shade, int32_t method);
void    polymer_postrotatesprite(void);
void    polymer_drawmaskwall(int32_t damaskwallcnt);
void    polymer_drawsprite(int32_t snum);
void    polymer_setanimatesprites(animatespritesptr animatesprites, int32_t x, int32_t y, int32_t z, int32_t a, int32_t smoothratio);
int16_t polymer_addlight(_prlight *light);
void    polymer_deletelight(int16_t lighti);
void    polymer_invalidatelights(void);
void    polymer_texinvalidate(void);
void    polymer_definehighpalookup(uint8_t basepalnum, uint8_t palnum, char *data);
bool    polymer_havehighpalookup(uint8_t basepalnum, uint8_t palnum);
void    polymer_setrorcallback(rorcallback callback);

extern _prsprite    *prsprites[MAXSPRITES];
static inline void polymer_invalidatesprite(int32_t i)
{
    if (prsprites[i])
        prsprites[i]->hash = 0xDEADBEEF;
}

extern GLuint       prartmaps[MAXTILES];
static inline void polymer_invalidateartmap(int32_t tilenum)
{
    if (prartmaps[tilenum])
    {
        glDeleteTextures(1, &prartmaps[tilenum]);
        prartmaps[tilenum] = 0;
    }
}

// Compare with eligible_for_tileshades()
static FORCE_INLINE int32_t polymer_eligible_for_artmap(int32_t tilenum, const pthtyp *pth) { return ((!pth || !pth->hicr) && tilenum < MAXUSERTILES); }
static FORCE_INLINE int     polymer_useartmapping(void) { return pr_artmapping && gltexfiltermode == 0; }

# ifdef POLYMER_C

// CORE
static void         polymer_displayrooms(int16_t sectnum);
static void         polymer_emptybuckets(void);
static _prbucket*   polymer_findbucket(int16_t tilenum, char pal);
static void         polymer_bucketplane(_prplane* plane);
static void         polymer_drawplane(_prplane* plane);
static inline void  polymer_inb4mirror(_prvert* buffer, const GLfloat* plane);
static void         polymer_animatesprites(void);
static void         polymer_freeboard(void);
// SECTORS
static int32_t      polymer_initsector(int16_t sectnum);
static int32_t      polymer_updatesector(int16_t sectnum);
static int32_t      polymer_buildfloor(int16_t sectnum);
static void         polymer_drawsector(int16_t sectnum, int32_t domasks);
// WALLS
static int32_t      polymer_initwall(int16_t wallnum);
static void         polymer_updatewall(int16_t wallnum);
static void         polymer_drawwall(int16_t sectnum, int16_t wallnum);
// HSR
static void         polymer_computeplane(_prplane* p);
static inline void  polymer_transformpoint(const float* inpos, float* pos, const float* matrix);
static inline void  polymer_pokesector(int16_t sectnum);
static void         polymer_extractfrustum(GLfloat* modelview, GLfloat* projection, float* frustum);
static inline int32_t polymer_planeinfrustum(_prplane const &plane, const float* frustum);
static inline void  polymer_scansprites(int16_t sectnum, tspriteptr_t tsprite, int32_t* spritesortcnt);
static void         polymer_updatesprite(int32_t snum);
// SKIES
static void         polymer_getsky(int16_t picnum, uint8_t pal, int8_t shade);
static void         polymer_drawsky(int16_t tilenum, char palnum, int8_t shade);
static void         polymer_initartsky(void);
static void         polymer_drawartsky(int16_t tilenum, char palnum, int8_t shade);
static void         polymer_drawartskyquad(int32_t p1, int32_t p2, GLfloat height);
static void         polymer_drawskybox(int16_t tilenum, char palnum, int8_t shade);
// MDSPRITES
static void         polymer_drawmdsprite(tspriteptr_t tspr);
static void         polymer_loadmodelvbos(md3model_t* m);
// MATERIALS
static void         polymer_getscratchmaterial(_prmaterial* material);
static _prbucket*   polymer_getbuildmaterial(_prmaterial* material, int16_t tilenum, char pal, int8_t shade, int8_t vis, int32_t cmeth);
static int32_t      polymer_bindmaterial(const _prmaterial *material, const int16_t* lights, int lightcount);
static void         polymer_unbindmaterial(int32_t programbits);
static _prprograminfo *polymer_compileprogram(int32_t programbits);
// LIGHTS
static void         polymer_removelight(int16_t lighti);
static void         polymer_updatelights(void);
static inline void  polymer_resetplanelights(_prplane* plane);
static void         polymer_addplanelight(_prplane* plane, int16_t lighti);
static inline void  polymer_deleteplanelight(_prplane* plane, int16_t lighti);
static int32_t      polymer_planeinlight(_prplane const &plane, _prlight const &light);
static inline void  polymer_invalidateplanelights(_prplane const &plane);
static void         polymer_invalidatesectorlights(int16_t sectnum);
static void         polymer_processspotlight(_prlight* light);
static int          polymer_culllight(int16_t lighti);
static void         polymer_prepareshadows(void);
// RENDER TARGETS
static void         polymer_initrendertargets(int32_t count);

#define INDICE(n) ((p->indices) ? (p->indices[(i+n)%(p->indicescount-1)]) : (((i+n)%(p->vertcount-1))))

#define SWITCH_CULL_DIRECTION { culledface = (culledface == GL_FRONT) ? GL_BACK : GL_FRONT; glCullFace(culledface); }

static FORCE_INLINE GLfloat dot2f(const GLfloat *v1, const GLfloat *v2) { return v1[0] * v2[0] + v1[1] * v2[1]; }
static FORCE_INLINE GLfloat dot3f(const GLfloat *v1, const GLfloat *v2) { return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; }
static FORCE_INLINE void relvec2f(const GLfloat *v1, const GLfloat *v2, GLfloat *out)
{
    out[0] = v2[0] - v1[0];
    out[1] = v2[1] - v1[1];
}

// the following from gle/vvector.h

/* ========================================================== */
/* determinant of matrix
 *
 * Computes determinant of matrix m, returning d
 */

#define DETERMINANT_3X3(d, m)                                   \
    {                                                           \
        d = m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]);  \
        d -= m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]); \
        d += m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); \
    }

/* ========================================================== */
/* i,j,th cofactor of a 4x4 matrix
 *
 */

#define COFACTOR_4X4_IJ(fac, m, i, j)            \
    {                                            \
        int ii[4], jj[4], k;                     \
                                                 \
        /* compute which row, columnt to skip */ \
        for (k = 0; k < i; k++) ii[k] = k;       \
        for (k = i; k < 3; k++) ii[k] = k + 1;   \
        for (k = 0; k < j; k++) jj[k] = k;       \
        for (k = j; k < 3; k++) jj[k] = k + 1;   \
                                                 \
        (fac) = m[ii[0]][jj[0]] * (m[ii[1]][jj[1]]*m[ii[2]][jj[2]]    \
                                 - m[ii[1]][jj[2]]*m[ii[2]][jj[1]]);  \
        (fac) -= m[ii[0]][jj[1]] * (m[ii[1]][jj[0]]*m[ii[2]][jj[2]]   \
                                  - m[ii[1]][jj[2]]*m[ii[2]][jj[0]]); \
        (fac) += m[ii[0]][jj[2]] * (m[ii[1]][jj[0]]*m[ii[2]][jj[1]]   \
                                  - m[ii[1]][jj[1]]*m[ii[2]][jj[0]]); \
        /* compute sign */                       \
        k = i + j;                               \
        if (k != (k / 2) * 2)                    \
            (fac) = -(fac);                      \
    }

/* ========================================================== */
/* determinant of matrix
 *
 * Computes determinant of matrix m, returning d
 */

#define DETERMINANT_4X4(d, m)            \
    {                                    \
        float cofac;                     \
        COFACTOR_4X4_IJ(cofac, m, 0, 0); \
        d = m[0][0] * cofac;             \
        COFACTOR_4X4_IJ(cofac, m, 0, 1); \
        d += m[0][1] * cofac;            \
        COFACTOR_4X4_IJ(cofac, m, 0, 2); \
        d += m[0][2] * cofac;            \
        COFACTOR_4X4_IJ(cofac, m, 0, 3); \
        d += m[0][3] * cofac;            \
    }

/* ========================================================== */
/* compute adjoint of matrix and scale
 *
 * Computes adjoint of matrix m, scales it by s, returning a
 */

#define SCALE_ADJOINT_3X3(a, s, m)                               \
    {                                                            \
        a[0][0] = (s) * (m[1][1] * m[2][2] - m[1][2] * m[2][1]); \
        a[1][0] = (s) * (m[1][2] * m[2][0] - m[1][0] * m[2][2]); \
        a[2][0] = (s) * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); \
                                                                 \
        a[0][1] = (s) * (m[0][2] * m[2][1] - m[0][1] * m[2][2]); \
        a[1][1] = (s) * (m[0][0] * m[2][2] - m[0][2] * m[2][0]); \
        a[2][1] = (s) * (m[0][1] * m[2][0] - m[0][0] * m[2][1]); \
                                                                 \
        a[0][2] = (s) * (m[0][1] * m[1][2] - m[0][2] * m[1][1]); \
        a[1][2] = (s) * (m[0][2] * m[1][0] - m[0][0] * m[1][2]); \
        a[2][2] = (s) * (m[0][0] * m[1][1] - m[0][1] * m[1][0]); \
    }

/* ========================================================== */
/* compute adjoint of matrix and scale
 *
 * Computes adjoint of matrix m, scales it by s, returning a
 */

#define SCALE_ADJOINT_4X4(a, s, m)                 \
    {                                              \
        for (int i = 0; i < 4; i++)                \
            for (int j = 0; j < 4; j++)            \
            {                                      \
                COFACTOR_4X4_IJ(a[j][i], m, i, j); \
                a[j][i] *= s;                      \
            }                                      \
    }

/* ========================================================== */
/* inverse of matrix
 *
 * Compute inverse of matrix a, returning determinant m and
 * inverse b
 */

#define INVERT_3X3(b, det, a)         \
    {                                 \
        DETERMINANT_3X3(det, a);      \
        float tmp = 1.f / (det);      \
        SCALE_ADJOINT_3X3(b, tmp, a); \
    }

/* ========================================================== */
/* inverse of matrix
 *
 * Compute inverse of matrix a, returning determinant m and
 * inverse b
 */

#define INVERT_4X4(b, det, a)         \
    {                                 \
        DETERMINANT_4X4(det, a);      \
        float tmp = 1.f / (det);      \
        SCALE_ADJOINT_4X4(b, tmp, a); \
    }

# endif // !POLYMER_C

#ifdef __cplusplus
}
#endif

#endif // !polymer_h_


code:
#ifndef polymost_h_
# define polymost_h_

#ifdef USE_OPENGL

#include "baselayer.h"  // glinfo
#include "glad/glad.h"
#include "hightile.h"

extern int32_t rendmode;
extern float gtang;
extern int polymost2d;
extern double gxyaspect;
extern float grhalfxdown10x;
extern float gcosang, gsinang, gcosang2, gsinang2;
extern float gchang, gshang, gctang, gstang, gvisibility;
extern float gvrcorrection;

struct glfiltermodes {
    const char *name;
    int32_t min,mag;
};
#define NUMGLFILTERMODES 6
extern struct glfiltermodes glfiltermodes[NUMGLFILTERMODES];

extern void Polymost_prepare_loadboard(void);

//void phex(char v, char *s);
void polymost_setuptexture(const int32_t dameth, int filter);
void uploadtexture(int32_t doalloc, vec2_t siz, int32_t texfmt, coltype *pic, vec2_t tsiz, int32_t dameth);
void uploadtextureindexed(int32_t doalloc, vec2_t offset, vec2_t siz, intptr_t tile);
void uploadbasepalette(int32_t basepalnum);
void uploadpalswap(int32_t palookupnum);
void polymost_drawsprite(int32_t snum);
void polymost_drawmaskwall(int32_t damaskwallcnt);
void polymost_dorotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
                             int8_t dashade, char dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend, int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, int32_t uniqid);
void polymost_fillpolygon(int32_t npoints);
void polymost_initosdfuncs(void);
void polymost_drawrooms(void);
void polymost_prepareMirror(int32_t dax, int32_t day, int32_t daz, fix16_t daang, fix16_t dahoriz, int16_t mirrorWall);
void polymost_completeMirror();
void polymost_startBufferedDrawing(int nn);
void polymost_bufferVert(vec3f_t const v, vec2f_t const t);
void polymost_finishBufferedDrawing(int mode);

int32_t polymost_maskWallHasTranslucency(uwalltype const * const wall);
int32_t polymost_spriteHasTranslucency(tspritetype const * const tspr);
int32_t polymost_spriteIsModelOrVoxel(tspritetype const * const tspr);

void polymost_disableProgram(void);
char polymost_getClamp(void);
void polymost_resetProgram(void);
void polymost_resetVertexPointers(void);
void polymost_setClamp(char clamp);
void polymost_setFogEnabled(char fogEnabled);
void polymost_setHalfTexelSize(vec2f_t const &halfTexelSize);
void polymost_setTexturePosSize(vec4f_t const &texturePosSize);
void polymost_setVisibility(float visibility);
void polymost_updatePalette(void);
void polymost_useColorOnly(char useColorOnly);
void polymost_useDetailMapping(char useDetailMapping);
void polymost_useGlowMapping(char useGlowMapping);
void polymost_usePaletteIndexing(char usePaletteIndexing);

GLuint polymost2_compileShader(GLenum shaderType, const char* const source, int* pLength = nullptr);

float* multiplyMatrix4f(float m0[4*4], const float m1[4*4]);

void polymost_initdrawpoly(void);
void polymost_glinit(void);
void polymost_glreset(void);

void polymost_init(void);

enum {
    INVALIDATE_ALL,
    INVALIDATE_ART,
    INVALIDATE_ALL_NON_INDEXED,
    INVALIDATE_ART_NON_INDEXED
};

void gltexinvalidate(int32_t dapicnum, int32_t dapalnum, int32_t dameth);
void gltexinvalidatetype(int32_t type);
int32_t polymost_printtext256(int32_t xpos, int32_t ypos, int16_t col, int16_t backcol, const char *name, char fontsize);

extern float curpolygonoffset;

extern float shadescale;
extern int32_t shadescale_unbounded;
extern uint8_t alphahackarray[MAXTILES];

#ifdef POLYMOST2
extern int32_t r_enablepolymost2;
#endif // POLYMOST2

#ifdef USE_GLEXT
extern int32_t r_vbocount;
extern int32_t r_glowmapping;
extern int32_t r_detailmapping;
#endif

extern int32_t r_animsmoothing;
extern int32_t r_downsize;
extern int32_t r_downsizevar;
extern int32_t r_drawpolyVertsBufferLength;
extern int32_t r_flatsky;
extern int32_t r_fullbrights;
extern int32_t r_npotwallmode;
extern int32_t r_parallaxskyclamping;
extern int32_t r_parallaxskypanning;
extern int32_t r_polygonmode;
extern int32_t r_polymostDebug;
extern int32_t r_shadeinterpolate;
extern int32_t r_skyzbufferhack;
extern int32_t r_useindexedcolortextures;
extern int32_t r_usenewshading;
extern int32_t r_usesamplerobjects;
extern int32_t r_usetileshades;
extern int32_t r_vertexarrays;
extern int32_t r_yshearing;
extern int32_t r_persistentStreamBuffer;

extern int32_t r_brightnesshack;

extern int32_t polymostcenterhoriz;
extern GLuint drawpolyVertsID;

enum tileshademodes
{
    TS_NONE,
    TS_SHADETABLE,
    TS_TEXTURE
};

extern float fogfactor[MAXPALOOKUPS];

// Compare with polymer_eligible_for_artmap()
static FORCE_INLINE int32_t eligible_for_tileshades(int32_t const picnum, int32_t const pal)
{
    return !usehightile || !hicfindsubst(picnum, pal, hictinting[pal].f & HICTINT_ALWAYSUSEART);
}

static FORCE_INLINE int polymost_useindexedtextures(void)
{
    return videoGetRenderMode() == REND_POLYMOST && r_useindexedcolortextures && gltexfiltermode == 0;
}

static FORCE_INLINE int polymost_usetileshades(void)
{
    int const idx = polymost_useindexedtextures();
    int const shd = idx || (r_usetileshades && !(globalflags & GLOBAL_NO_GL_TILESHADES));
    return idx && shd ? TS_SHADETABLE : shd ? TS_TEXTURE : TS_NONE;
}

static FORCE_INLINE float polymost_getanisotropy(int filtered = 0)
{
    return filtered == 0 && polymost_useindexedtextures() ? 1.f : clamp<float>(glanisotropy, 1.f, glinfo.maxanisotropy);
}

static inline float getshadefactor(int32_t const shade, int32_t const pal)
{
    // 8-bit tiles, i.e. non-hightiles and non-models, don't get additional
    // glColor() shading with r_usetileshades!
    if (videoGetRenderMode() == REND_POLYMOST && polymost_usetileshades() != TS_NONE && eligible_for_tileshades(globalpicnum, globalpal))
        return 1.f;

    float const fshade = fogfactor[pal] != 0.f ? (float)shade / fogfactor[pal] : 0.f;

    if (r_usenewshading == 4)
        return max(min(1.f - (fshade * shadescale / frealmaxshade), 1.f), 0.f);

    float const shadebound = (float)((shadescale_unbounded || shade>=numshades) ? numshades : numshades-1);
    float const scaled_shade = fshade*shadescale;
    float const clamped_shade = min(max(scaled_shade, 0.f), shadebound);

    return ((float)(numshades-clamped_shade))/(float)numshades;
}

#define POLYMOST_CHOOSE_FOG_PAL(fogpal, pal) \
    ((fogpal) ? (fogpal) : (pal))
static FORCE_INLINE int32_t get_floor_fogpal(usectorptr_t const sec)
{
    return POLYMOST_CHOOSE_FOG_PAL(sec->fogpal, sec->floorpal);
}
static FORCE_INLINE int32_t get_ceiling_fogpal(usectorptr_t const sec)
{
    return POLYMOST_CHOOSE_FOG_PAL(sec->fogpal, sec->ceilingpal);
}
static FORCE_INLINE int32_t fogshade(int32_t const shade, int32_t const pal)
{
    polytintflags_t const tintflags = hictinting[pal].f;
    return (globalflags & GLOBAL_NO_GL_FOGSHADE || tintflags & HICTINT_NOFOGSHADE) ? 0 : shade;
}

static FORCE_INLINE int check_nonpow2(int32_t const x)
{
    return (x > 1 && (x&(x-1)));
}

// Are we using the mode that uploads non-power-of-two wall textures like they
// render in classic?
static FORCE_INLINE int polymost_is_npotmode(void)
{
    // The glinfo.texnpot check is so we don't have to deal with that case in
    // gloadtile_art().
    return glinfo.texnpot &&
        // r_npotwallmode is NYI for hightiles. We require r_hightile off
        // because in calc_ypanning(), the repeat would be multiplied by a
        // factor even if no modified texture were loaded.
        !usehightile &&
#ifdef NEW_MAP_FORMAT
        g_loadedMapVersion < 10 &&
#endif
        r_npotwallmode == 1;
}

// Flags of the <dameth> argument of various functions
enum {
    DAMETH_NOMASK = 0,
    DAMETH_MASK = 1,
    DAMETH_TRANS1 = 2,
    DAMETH_TRANS2 = 3,

    DAMETH_MASKPROPS = 3,

    DAMETH_CLAMPED = 4,

    DAMETH_WALL = 32,  // signals a texture for a wall (for r_npotwallmode)

    DAMETH_INDEXED = 512,

    DAMETH_N64 = 1024,
    DAMETH_N64_INTENSIVITY = 2048,
    DAMETH_N64_SCALED = 2097152,

    // used internally by polymost_domost
    DAMETH_BACKFACECULL = -1,

    // used internally by uploadtexture
    DAMETH_NODOWNSIZE = 4096,
    DAMETH_HI = 8192,
    DAMETH_NOFIX = 16384,
    DAMETH_NOTEXCOMPRESS = 32768,
    DAMETH_HASALPHA = 65536,
    DAMETH_ONEBITALPHA = 131072,
    DAMETH_ARTIMMUNITY = 262144,

    DAMETH_HASFULLBRIGHT = 524288,
    DAMETH_NPOTWALL = 1048576,

    DAMETH_UPLOADTEXTURE_MASK =
        DAMETH_HI |
        DAMETH_NODOWNSIZE |
        DAMETH_NOFIX |
        DAMETH_NOTEXCOMPRESS |
        DAMETH_HASALPHA |
        DAMETH_ONEBITALPHA |
        DAMETH_ARTIMMUNITY |
        DAMETH_HASFULLBRIGHT |
        DAMETH_NPOTWALL,
};

#define DAMETH_NARROW_MASKPROPS(dameth) (((dameth)&(~DAMETH_TRANS1))|(((dameth)&DAMETH_TRANS1)>>1))
EDUKE32_STATIC_ASSERT(DAMETH_NARROW_MASKPROPS(DAMETH_MASKPROPS) == DAMETH_MASK);
EDUKE32_STATIC_ASSERT(DAMETH_NARROW_MASKPROPS(DAMETH_CLAMPED) == DAMETH_CLAMPED);

#define TO_DAMETH_NODOWNSIZE(hicr_flags) (((hicr_flags)&HICR_NODOWNSIZE)<<8)
EDUKE32_STATIC_ASSERT(TO_DAMETH_NODOWNSIZE(HICR_NODOWNSIZE) == DAMETH_NODOWNSIZE);
#define TO_DAMETH_NOTEXCOMPRESS(hicr_flags) (((hicr_flags)&HICR_NOTEXCOMPRESS)<<15)
EDUKE32_STATIC_ASSERT(TO_DAMETH_NOTEXCOMPRESS(HICR_NOTEXCOMPRESS) == DAMETH_NOTEXCOMPRESS);
#define TO_DAMETH_ARTIMMUNITY(hicr_flags) (((hicr_flags)&HICR_ARTIMMUNITY)<<13)
EDUKE32_STATIC_ASSERT(TO_DAMETH_ARTIMMUNITY(HICR_ARTIMMUNITY) == DAMETH_ARTIMMUNITY);
#define TO_DAMETH_INDEXED(hicr_flags) (((hicr_flags)&HICR_INDEXED)<<3)
EDUKE32_STATIC_ASSERT(TO_DAMETH_INDEXED(HICR_INDEXED) == DAMETH_INDEXED);

// Do we want a NPOT-y-as-classic texture for this <dameth> and <ysiz>?
static FORCE_INLINE int polymost_want_npotytex(int32_t dameth, int32_t ysiz)
{
    return videoGetRenderMode() != REND_POLYMER &&  // r_npotwallmode NYI in Polymer
        polymost_is_npotmode() && (dameth&DAMETH_WALL) && check_nonpow2(ysiz);
}

// pthtyp pth->flags bits
enum pthtyp_flags {
    PTH_CLAMPED = 1,
    PTH_HIGHTILE = 2,
    PTH_SKYBOX = 4,
    PTH_HASALPHA = 8,
    PTH_HASFULLBRIGHT = 16,
    PTH_NPOTWALL = DAMETH_WALL,  // r_npotwallmode=1 generated texture
    PTH_FORCEFILTER = 64,

    PTH_INVALIDATED = 128,

    PTH_NOTRANSFIX = 256, // fixtransparency() bypassed

    PTH_INDEXED = 512,
    PTH_ONEBITALPHA = 1024,

    PTH_N64 = 2048,
    PTH_N64_INTENSIVITY = 4096,
    PTH_N64_SCALED = 8192,

    // temporary until I create separate flags for samplers
    PTH_DEPTH_SAMPLER = 16384,
    PTH_TEMP_SKY_HACK = 32768
};

typedef struct pthtyp_t
{
    struct pthtyp_t *next;
    struct pthtyp_t *ofb; // fullbright pixels
    hicreplctyp     *hicr;

    uint32_t        glpic;
    vec2f_t         scale;
    vec2_t          siz;
    int16_t         picnum;

    uint16_t        flags; // see pthtyp_flags
    polytintflags_t effects;
    char            palnum;
    char            shade;
    char            skyface;
} pthtyp;

// DAMETH -> PTH conversions
#define TO_PTH_CLAMPED(dameth) (((dameth)&DAMETH_CLAMPED)>>2)
EDUKE32_STATIC_ASSERT(TO_PTH_CLAMPED(DAMETH_CLAMPED) == PTH_CLAMPED);
#define TO_PTH_NOTRANSFIX(dameth) ((((~(dameth))&DAMETH_MASK)<<8)&(((~(dameth))&DAMETH_TRANS1)<<7))
EDUKE32_STATIC_ASSERT(TO_PTH_NOTRANSFIX(DAMETH_NOMASK) == PTH_NOTRANSFIX);
EDUKE32_STATIC_ASSERT(TO_PTH_NOTRANSFIX(DAMETH_MASK) == 0);
EDUKE32_STATIC_ASSERT(TO_PTH_NOTRANSFIX(DAMETH_TRANS1) == 0);
EDUKE32_STATIC_ASSERT(TO_PTH_NOTRANSFIX(DAMETH_MASKPROPS) == 0);
#define TO_PTH_INDEXED(dameth) ((dameth)&DAMETH_INDEXED)
EDUKE32_STATIC_ASSERT(TO_PTH_INDEXED(DAMETH_INDEXED) == PTH_INDEXED);
#define TO_PTH_N64(dameth) (((dameth)&DAMETH_N64)<<1)
EDUKE32_STATIC_ASSERT(TO_PTH_N64(DAMETH_N64) == PTH_N64);
#define TO_PTH_N64_INTENSIVITY(dameth) (((dameth)&DAMETH_N64_INTENSIVITY)<<1)
EDUKE32_STATIC_ASSERT(TO_PTH_N64_INTENSIVITY(DAMETH_N64_INTENSIVITY) == PTH_N64_INTENSIVITY);
#define TO_PTH_N64_SCALED(dameth) (((dameth)&DAMETH_N64_SCALED)>>8)
EDUKE32_STATIC_ASSERT(TO_PTH_N64_SCALED(DAMETH_N64_SCALED) == PTH_N64_SCALED);

extern void gloadtile_art(int32_t,int32_t,int32_t,int32_t,int32_t,pthtyp *,int32_t);
extern int32_t gloadtile_hi(int32_t,int32_t,int32_t,hicreplctyp *,int32_t,pthtyp *,int32_t,polytintflags_t);
extern coltype *gloadtruecolortile_mdloadskin_shared(char* fn, int32_t picfillen, vec2_t * tsiz, vec2_t * siz, char * onebitalpha, polytintflags_t effect, int32_t dapalnum, char* al);
extern int32_t drawingskybox;
extern int32_t hicprecaching;
extern float fcosglobalang, fsinglobalang;
extern float fxdim, fydim, fydimen, fviewingrange;
extern float fsearchx, fsearchy;

extern char ptempbuf[MAXWALLSB<<1];

extern hitdata_t polymost_hitdata;

typedef struct
{
    uint32_t rev;
    vec2f_t fsin;
    int16_t wall;
    int8_t dist;
    int8_t invalid;
} wallspriteinfo_t;

// needs to be this high for XXX-Stacy because the bad sprite in that one isn't even properly ornamented onto the wall!
#define MAXINTERSECTIONANGDIFF (4.5f)
#define MAXINTERSECTIONLINEDIST 1

extern wallspriteinfo_t ornament[MAXSPRITES];
extern void polymost_checkornamentedsprite(tspriteptr_t tspr, int16_t *wallnum, wallspriteinfo_t* ws);
extern int32_t polymost_findintersectingwall(tspritetype const &tspr);
extern int32_t polymost_lintersect(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x3, int32_t y3, int32_t x4, int32_t y4);

static FORCE_INLINE bool polymost_testintersection(vec3_t const &pos, vec2_t const &v, int16_t wallnum)
{
    return ((pos.x - v.x) + (pos.x + v.x)) == (wall[wallnum].x + POINT2(wallnum).x)
        || ((pos.y - v.y) + (pos.y + v.y)) == (wall[wallnum].y + POINT2(wallnum).y)
        || polymost_lintersect(pos.x - v.x, pos.y - v.y, pos.x + v.x, pos.y + v.y, wall[wallnum].x, wall[wallnum].y, POINT2(wallnum).x, POINT2(wallnum).y);
}

extern void polymost_setupglowtexture(const int32_t texunit, const int32_t glpic, const int32_t flags);
extern void polymost_setupdetailtexture(const int32_t texunit, const int32_t glpic, const int32_t flags);

#endif

#endif

repo_name: orochi/nblood

license: mit


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)
// by the EDuke32 team (development@voidpoint.com)

#ifndef pragmas_h_
#define pragmas_h_

#include "libdivide_config.h"

#ifdef __cplusplus
extern "C" {
#endif

#define EDUKE32_GENERATE_PRAGMAS                                                                            \
    EDUKE32_SCALER_PRAGMA(1)  EDUKE32_SCALER_PRAGMA(2)  EDUKE32_SCALER_PRAGMA(3)  EDUKE32_SCALER_PRAGMA(4)  \
    EDUKE32_SCALER_PRAGMA(5)  EDUKE32_SCALER_PRAGMA(6)  EDUKE32_SCALER_PRAGMA(7)  EDUKE32_SCALER_PRAGMA(8)  \
    EDUKE32_SCALER_PRAGMA(9)  EDUKE32_SCALER_PRAGMA(10) EDUKE32_SCALER_PRAGMA(11) EDUKE32_SCALER_PRAGMA(12) \
    EDUKE32_SCALER_PRAGMA(13) EDUKE32_SCALER_PRAGMA(14) EDUKE32_SCALER_PRAGMA(15) EDUKE32_SCALER_PRAGMA(16) \
    EDUKE32_SCALER_PRAGMA(17) EDUKE32_SCALER_PRAGMA(18) EDUKE32_SCALER_PRAGMA(19) EDUKE32_SCALER_PRAGMA(20) \
    EDUKE32_SCALER_PRAGMA(21) EDUKE32_SCALER_PRAGMA(22) EDUKE32_SCALER_PRAGMA(23) EDUKE32_SCALER_PRAGMA(24) \
    EDUKE32_SCALER_PRAGMA(25) EDUKE32_SCALER_PRAGMA(26) EDUKE32_SCALER_PRAGMA(27) EDUKE32_SCALER_PRAGMA(28) \
    EDUKE32_SCALER_PRAGMA(29) EDUKE32_SCALER_PRAGMA(30) EDUKE32_SCALER_PRAGMA(31)

#if !defined(NOASM) && defined __cplusplus
extern "C" {
#endif
extern int32_t reciptable[2048], fpuasm;
#if !defined(NOASM) && defined __cplusplus
}
#endif

// break the C version of divscale out from the others
// because asm version overflows in drawmapview()

#define qw(x) ((int64_t)(x))  // quadword cast
#define dw(x) ((int32_t)(x))  // doubleword cast
#define wo(x) ((int16_t)(x))  // word cast
#define by(x) ((uint8_t)(x))  // byte cast

#define DIVTABLESIZE 16384
extern void initdivtables(void);

extern libdivide::libdivide_s64_t divtable64[DIVTABLESIZE];
extern libdivide::libdivide_s32_t divtable32[DIVTABLESIZE];

extern libdivide::libdivide_s64_branchfree_t bfdivtable64[DIVTABLESIZE];
extern libdivide::libdivide_s32_branchfree_t bfdivtable32[DIVTABLESIZE];

extern int64_t lastd_s64;
extern int64_t lastd_s64_b;

extern int32_t lastd_s32;
extern int32_t lastd_s32_b;

static inline uint32_t divideu32(uint32_t const n, uint32_t const d)
{
    using namespace libdivide;

    static libdivide_u32_t udiv;
    static uint32_t lastd;

    if (d != lastd)
        udiv = libdivide_u32_gen((lastd = d));

    return libdivide_u32_do(n, &udiv);
}

static inline uint64_t divideu64(uint64_t const n, uint64_t const d)
{
    using namespace libdivide;

    static libdivide_u64_t udiv;
    static uint64_t lastd;

    if (d != lastd)
        udiv = libdivide_u64_gen((lastd = d));

    return libdivide_u64_do(n, &udiv);
}

static inline uint32_t divideu32_branchfree(uint32_t const n, uint32_t const d)
{
    using namespace libdivide;

    static libdivide_u32_branchfree_t udiv;
    static uint32_t lastd;

    if (d != lastd)
        udiv = libdivide_u32_branchfree_gen((lastd = d));

    return libdivide_u32_branchfree_do(n, &udiv);
}

static inline uint64_t divideu64_branchfree(uint64_t const n, uint64_t const d)
{
    using namespace libdivide;

    static libdivide_u64_branchfree_t udiv;
    static uint64_t lastd;

    if (d != lastd)
        udiv = libdivide_u64_branchfree_gen((lastd = d));

    return libdivide_u64_branchfree_do(n, &udiv);
}

static inline int64_t tabledivide64(int64_t const n, int64_t const d)
{
    using namespace libdivide;

    if ((d != lastd_s64) & !((uint64_t)d < DIVTABLESIZE))
        divtable64[0] = libdivide_s64_gen((lastd_s64 = d));

    return libdivide_s64_do(n, &divtable64[((uint64_t)d < DIVTABLESIZE) * d]);
}

static inline int32_t tabledivide32(int32_t const n, int32_t const d)
{
    using namespace libdivide;

    if ((d != lastd_s32) & !((uint32_t)d < DIVTABLESIZE))
        divtable32[0] = libdivide_s32_gen((lastd_s32 = d));

    return libdivide_s32_do(n, &divtable32[((uint32_t)d < DIVTABLESIZE) * d]);
}

static inline int64_t tabledivide64_branchfree(int64_t const n, int64_t const d)
{
    using namespace libdivide;

    if ((d != lastd_s64_b) & !((uint64_t)d < DIVTABLESIZE))
        bfdivtable64[0] = libdivide_s64_branchfree_gen((lastd_s64_b = d));

    return libdivide_s64_branchfree_do(n, &bfdivtable64[((uint64_t)d < DIVTABLESIZE) * d]);
}

static inline int32_t tabledivide32_branchfree(int32_t const n, int32_t const d)
{
    using namespace libdivide;

    if ((d != lastd_s32_b) & !((uint32_t)d < DIVTABLESIZE))
        bfdivtable32[0] = libdivide_s32_branchfree_gen((lastd_s32_b = d));

    return libdivide_s32_branchfree_do(n, &bfdivtable32[((uint32_t)d < DIVTABLESIZE) * d]);
}

extern decltype(divideu32) *divideu32_noinline;
extern decltype(divideu64) *divideu64_noinline;
extern decltype(tabledivide32) *tabledivide32_noinline;
extern decltype(tabledivide64)* tabledivide64_noinline;

extern decltype(divideu32_branchfree)* divideu32_branchfree_noinline;
extern decltype(divideu64_branchfree)* divideu64_branchfree_noinline;
extern decltype(tabledivide32_branchfree) *tabledivide32_branchfree_noinline;
extern decltype(tabledivide64_branchfree) *tabledivide64_branchfree_noinline;

#ifdef GEKKO
static inline int32_t divscale(int32_t eax, int32_t ebx, int32_t ecx) { return dw(tabledivide64(ldexp(eax, ecx), ebx)); }
#else
static inline int32_t divscale(int32_t eax, int32_t ebx, int32_t ecx) { return dw(tabledivide64(qw(eax) << by(ecx), ebx)); }
#endif

static inline int64_t divscale64(int64_t eax, int64_t ebx, int64_t ecx) { return tabledivide64(eax << ecx, ebx); }

#define EDUKE32_SCALER_PRAGMA(a) \
    static FORCE_INLINE int32_t divscale##a(int32_t eax, int32_t ebx) { return divscale(eax, ebx, a); }
EDUKE32_GENERATE_PRAGMAS EDUKE32_SCALER_PRAGMA(32)
#undef EDUKE32_SCALER_PRAGMA

static inline int32_t scale(int32_t eax, int32_t edx, int32_t ecx)
{
    return dw(tabledivide64(qw(eax) * edx, ecx));
}

static FORCE_INLINE int32_t scaleadd(int32_t eax, int32_t edx, int32_t addend, int32_t ecx)
{
    return dw(tabledivide64(qw(eax) * edx + addend, ecx));
}

static inline int32_t roundscale(int32_t eax, int32_t edx, int32_t ecx)
{
    return scaleadd(eax, edx, ecx / 2, ecx);
}

#if defined(__GNUC__) && defined(GEKKO)

// GCC Inline Assembler version (PowerPC)
#include "pragmas_ppc.h"

#elif defined(__GNUC__) && defined(__i386__) && !defined(NOASM)

// GCC Inline Assembler version (x86)
#include "pragmas_x86_gcc.h"

#elif defined(_MSC_VER) && !defined(NOASM)  // __GNUC__

// Microsoft C inline assembler
#include "pragmas_x86_msvc.h"

#elif defined(__arm__)  // _MSC_VER

// GCC Inline Assembler version (ARM)
#include "pragmas_arm.h"

#endif

//
// Generic C
//

#ifndef pragmas_have_mulscale

#define EDUKE32_SCALER_PRAGMA(a)                                                                                \
    static FORCE_INLINE CONSTEXPR int32_t mulscale##a(int32_t eax, int32_t edx) { return dw((qw(eax) * edx) >> by(a)); }             \
    static FORCE_INLINE CONSTEXPR int32_t dmulscale##a(int32_t eax, int32_t edx, int32_t esi, int32_t edi)                           \
    {                                                                                \
        return dw(((qw(eax) * edx) + (qw(esi) * edi)) >> by(a));                                                                     \
    }                                                                                \
    static FORCE_INLINE CONSTEXPR int32_t tmulscale##a(int32_t eax, int32_t edx, int32_t ebx, int32_t ecx, int32_t esi, int32_t edi) \
    {                                                                                \
        return dw(((qw(eax) * edx) + (qw(ebx) * ecx) + (qw(esi) * edi)) >> by(a));                                                   \
    }

EDUKE32_GENERATE_PRAGMAS EDUKE32_SCALER_PRAGMA(32)

#undef EDUKE32_SCALER_PRAGMA

#endif

#ifdef __cplusplus
}
template <typename T>
static FORCE_INLINE void swap(T * const a, T * const b)
{
    T const t = *a;
    *a = *b;
    *b = t;
}
#define swapptr swap
extern "C" {
#else
static FORCE_INLINE void swapptr(void *a, void *b)
{
    intptr_t const t = *(intptr_t*) a;
    *(intptr_t*) a = *(intptr_t*) b;
    *(intptr_t*) b = t;
}
#endif

#ifndef pragmas_have_swaps
#ifdef __cplusplus
#define swapchar swap
#define swapshort swap
#define swaplong swap
#define swapfloat swap
#define swapdouble swap
#define swap64bit swap
#else
static FORCE_INLINE void swapchar(void *a, void *b)
{
    char const t = *(char *)b;
    *(char *)b = *(char *)a;
    *(char *)a = t;
}
static FORCE_INLINE void swapshort(void *a, void *b)
{
    int16_t const t = *(int16_t *)b;
    *(int16_t *)b = *(int16_t *)a;
    *(int16_t *)a = t;
}
static FORCE_INLINE void swaplong(void *a, void *b)
{
    int32_t const t = *(int32_t *)b;
    *(int32_t *)b = *(int32_t *)a;
    *(int32_t *)a = t;
}
static FORCE_INLINE void swapfloat(void *a, void *b)
{
    float const t = *(float *)b;
    *(float *)b = *(float *)a;
    *(float *)a = t;
}
static FORCE_INLINE void swapdouble(void *a, void *b)
{
    double const t = *(double *)b;
    *(double *)b = *(double *)a;
    *(double *)a = t;
}
static FORCE_INLINE void swap64bit(void *a, void *b)
{
    uint64_t const t = *(uint64_t *)b;
    *(uint64_t *)b = *(uint64_t *)a;
    *(uint64_t *)a = t;
}
#endif
static FORCE_INLINE void swapchar2(void *a, void *b, int32_t s)
{
    swapchar((char *)a, (char *)b);
    swapchar((char *)a + 1, (char *)b + s);
}
#endif

static FORCE_INLINE CONSTEXPR char readpixel(void *s) { return *(char *)s; }
static FORCE_INLINE void drawpixel(void *s, char a) { *(char *)s = a; }

#ifndef pragmas_have_klabs
#if 0
static FORCE_INLINE int32_t klabs(int32_t const a)
{
    uint32_t const m = a >> (sizeof(uint32_t) * CHAR_BIT - 1);
    return (a ^ m) - m;
}
#else
# ifdef __cplusplus
// some toolchains use the double version of abs for small int types, so avoid that
static FORCE_INLINE int32_t klabs(int32_t const a) { return abs(a); }
# else
#  define klabs(x) abs(x)
# endif
#endif
#endif
#ifndef pragmas_have_ksgn
static FORCE_INLINE CONSTEXPR int ksgn(int32_t a) { return (a > 0) - (a < 0); }
#endif

#ifndef pragmas_have_mulscale
static FORCE_INLINE CONSTEXPR int32_t mulscale(int32_t eax, int32_t edx, int32_t ecx) { return dw((qw(eax) * edx) >> by(ecx)); }
static FORCE_INLINE CONSTEXPR int32_t dmulscale(int32_t eax, int32_t edx, int32_t esi, int32_t edi, int32_t ecx)
{
    return dw(((qw(eax) * edx) + (qw(esi) * edi)) >> by(ecx));
}
#endif

#ifndef pragmas_have_qinterpolatedown16
void qinterpolatedown16(intptr_t bufptr, int32_t num, int32_t val, int32_t add);
void qinterpolatedown16short(intptr_t bufptr, int32_t num, int32_t val, int32_t add);
#endif

#ifndef pragmas_have_clearbuf
void clearbuf(void *d, int32_t c, int32_t a);
#endif
#ifndef pragmas_have_copybuf
void copybuf(const void *s, void *d, int32_t c);
#endif
#ifndef pragmas_have_swaps
void swapbuf4(void *a, void *b, int32_t c);
#endif

#ifndef pragmas_have_clearbufbyte
void clearbufbyte(void *D, int32_t c, int32_t a);
#endif
#ifndef pragmas_have_copybufbyte
void copybufbyte(const void *S, void *D, int32_t c);
#endif
#ifndef pragmas_have_copybufreverse
void copybufreverse(const void *S, void *D, int32_t c);
#endif

#ifndef pragmas_have_krecipasm
static inline int32_t krecipasm(int32_t i)
{
    // Ken did this
    union { int32_t i; float f; } x;
    x.f = (float)i;
    i = x.i;
    return ((reciptable[(i >> 12) & 2047] >> (((i - 0x3f800000) >> 23) & 31)) ^ (i >> 31));
}
#endif

#undef qw
#undef dw
#undef wo
#undef by

static inline void swapbufreverse(void *s, void *d, int32_t c)
{
    uint8_t *src = (uint8_t *)s, *dst = (uint8_t *)d;
    Bassert(c >= 4);

    do
    {
        swapchar(dst, src);
        swapchar(dst + 1, src - 1);
        swapchar(dst + 2, src - 2);
        swapchar(dst + 3, src - 3);
        dst += 4, src -= 4;
    } while ((c -= 4) > 4);

    while (c--)
        swapchar(dst++, src--);
}

#ifdef __cplusplus
}
#endif

#endif  // pragmas_h_


code:
//
// GCC Inline Assembler version (ARM)
//

#ifndef pragmas_arm_h_
#define pragmas_arm_h_

// :(

#endif


code:
// GCC Inline Assembler version (PowerPC)

#ifdef pragmas_h_
#ifndef pragmas_ppc_h_
#define pragmas_ppc_h_

#define pragmas_have_mulscale

#define EDUKE32_SCALER_PRAGMA(x) \
static inline int32_t mulscale##x(int32_t a, int32_t d) \
{ \
    int32_t mullo, mulhi; \
    __asm__ ( \
        " mullw  %0, %2, %3\n" \
        " mulhw  %1, %2, %3\n" \
        " srwi   %0, %0, %4\n" \
        " insrwi %0, %1, %4, 0\n" \
        : "=&r"(mullo), "=r"(mulhi) \
        : "r"(a), "r"(d), "i"(x) \
    ); \
    return mullo; \
} \
static inline int32_t dmulscale##x(int32_t a, int32_t d, int32_t S, int32_t D) \
{ \
    int32_t mulhi, mullo, sumhi, sumlo; \
    __asm__ ( \
        " mullw  %0, %4, %5\n" \
        " mulhw  %1, %4, %5\n" \
        " mullw  %2, %6, %7\n" \
        " mulhw  %3, %6, %7\n" \
        " addc   %0, %0, %2\n" \
        " adde   %1, %1, %3\n" \
        " srwi   %0, %0, %8\n" \
        " insrwi %0, %1, %8, 0\n" \
        : "=&r"(sumlo), "=&r"(sumhi), "=&r"(mullo), "=r"(mulhi) \
        : "r"(a), "r"(d), "r"(S), "r"(D), "i"(x) \
        : "xer" \
    ); \
    return sumlo; \
} \
static inline int32_t tmulscale##x(int32_t a, int32_t d, int32_t b, int32_t c, int32_t S, int32_t D) \
{ \
    int32_t mulhi, mullo, sumhi, sumlo; \
    __asm__( \
        " mullw  %0, %4, %5\n" \
        " mulhw  %1, %4, %5\n" \
        " mullw  %2, %6, %7\n" \
        " mulhw  %3, %6, %7\n" \
        " addc   %0, %0, %2\n" \
        " adde   %1, %1, %3\n" \
        " mullw  %2, %8, %9\n" \
        " mulhw  %3, %8, %9\n" \
        " addc   %0, %0, %2\n" \
        " adde   %1, %1, %3\n" \
        " srwi   %0, %0, %10\n" \
        " insrwi %0, %1, %10, 0\n" \
        : "=&r"(sumlo), "=&r"(sumhi), "=&r"(mullo), "=&r"(mulhi) \
        : "r"(a), "r"(d), "r"(b), "r"(c), "r"(S), "r"(D), "i"(x) \
        : "xer" \
        ); \
    return sumlo; \
} \

EDUKE32_GENERATE_PRAGMAS
#undef EDUKE32_SCALER_PRAGMA

static inline int32_t mulscale(int32_t a, int32_t d, int32_t c)
{
    int32_t mullo, mulhi;
    __asm__(
        " mullw  %0, %2, %3\n"
        " mulhw  %1, %2, %3\n"
        " srw    %0, %0, %4\n"
        " slw    %1, %1, %5\n"
        " or     %0, %0, %1\n"
        : "=&r"(mullo), "=&r"(mulhi)
        : "r"(a), "r"(d), "r"(c), "r"(32-c)
        : "xer"
        );
    return mullo;
}

static inline int32_t mulscale32(int32_t a, int32_t d)
{
    int32_t mulhi;
    __asm__(
        " mulhw %0, %1, %2\n"
        : "=r"(mulhi)
        : "r"(a), "r"(d)
        );
    return mulhi;
}

static inline int32_t dmulscale(int32_t a, int32_t d, int32_t S, int32_t D, int32_t c)
{
    int32_t mulhi, mullo, sumhi, sumlo;
    __asm__(
        " mullw  %0, %4, %5\n"
        " mulhw  %1, %4, %5\n"
        " mullw  %2, %6, %7\n"
        " mulhw  %3, %6, %7\n"
        " addc   %0, %0, %2\n"
        " adde   %1, %1, %3\n"
        " srw    %0, %0, %8\n"
        " slw    %1, %1, %9\n"
        " or     %0, %0, %1\n"
        : "=&r"(sumlo), "=&r"(sumhi), "=&r"(mullo), "=&r"(mulhi)
        : "r"(a), "r"(d), "r"(S), "r"(D), "r"(c), "r"(32-c)
        : "xer"
        );
    return sumlo;
}

static inline int32_t dmulscale32(int32_t a, int32_t d, int32_t S, int32_t D)
{
    int32_t mulhi, mullo, sumhi, sumlo;
    __asm__(\
        " mullw  %0, %4, %5\n" \
        " mulhw  %1, %4, %5\n" \
        " mullw  %2, %6, %7\n" \
        " mulhw  %3, %6, %7\n" \
        " addc   %0, %0, %2\n" \
        " adde   %1, %1, %3\n" \
        : "=&r"(sumlo), "=&r"(sumhi), "=&r"(mullo), "=r"(mulhi)
        : "r"(a), "r"(d), "r"(S), "r"(D)
        : "xer"
        );
    return sumhi;
}

static inline int32_t tmulscale32(int32_t a, int32_t d, int32_t b, int32_t c, int32_t S, int32_t D)
{
    int32_t mulhi, mullo, sumhi, sumlo;
    __asm__(
        " mullw  %0, %4, %5\n"
        " mulhw  %1, %4, %5\n"
        " mullw  %2, %6, %7\n"
        " mulhw  %3, %6, %7\n"
        " addc   %0, %0, %2\n"
        " adde   %1, %1, %3\n"
        " mullw  %2, %8, %9\n"
        " mulhw  %3, %8, %9\n"
        " addc   %0, %0, %2\n"
        " adde   %1, %1, %3\n"
        : "=&r"(sumlo), "=&r"(sumhi), "=&r"(mullo), "=&r"(mulhi)
        : "r"(a), "r"(d), "r"(b), "r"(c), "r"(S), "r"(D)
        : "xer"
    );
    return sumhi;
}

#define pragmas_have_klabs

static inline int32_t klabs(int32_t a)
{
    int32_t mask;
    __asm__(
        " srawi  %0, %1, 31\n"
        " xor    %1, %0, %1\n"
        " subf   %1, %0, %1\n"
        : "=&r"(mask), "+r"(a)
        :
        : "xer"
        );
    return a;
}

#define pragmas_have_ksgn

static inline int ksgn(int32_t a)
{
    int32_t s, t;
    __asm__(
        " neg    %1, %2\n"
        " srawi  %0, %2, 31\n"
        " srwi   %1, %1, 31\n"
        " or	 %1, %1, %0\n"
        : "=r"(t), "=&r"(s)
        : "r"(a)
        : "xer"
        );
    return s;
}

#endif // pragmas_ppc_h_
#endif // pragmas_h_


code:
//
// Microsoft C inline assembler
//

//{{{

#ifdef pragmas_h_
#ifndef pragmas_x86_h_
#define pragmas_x86_h_

#define pragmas_have_mulscale

static __inline int32_t mulscale(int32_t a, int32_t d, int32_t c)
{
    _asm {
        mov ecx, c
            mov eax, a
            imul d
            shrd eax, edx, cl
    }
}

#define EDUKE32_SCALER_PRAGMA(x) \
static __inline int32_t mulscale##x (int32_t a, int32_t d) \
{ \
    _asm mov eax, a \
    _asm imul d \
    _asm shrd eax, edx, x \
} \
static __inline int32_t dmulscale##x (int32_t a, int32_t d, int32_t S, int32_t D) \
{ \
    _asm mov eax, a \
    _asm imul d \
    _asm mov ebx, eax \
    _asm mov eax, S \
    _asm mov esi, edx \
    _asm imul D \
    _asm add eax, ebx \
    _asm adc edx, esi \
    _asm shrd eax, edx, x \
} \
static __inline int32_t tmulscale##x (int32_t a, int32_t d, int32_t b, int32_t c, int32_t S, int32_t D) \
{ \
    _asm mov eax, a \
    _asm mov ebx, b \
    _asm imul d \
    _asm xchg eax, ebx \
    _asm mov ecx, c \
    _asm xchg edx, ecx \
    _asm imul edx \
    _asm add ebx, eax \
    _asm adc ecx, edx \
    _asm mov eax, S \
    _asm imul D \
    _asm add eax, ebx \
    _asm adc edx, ecx \
    _asm shrd eax, edx, x \
} \

EDUKE32_GENERATE_PRAGMAS
#undef EDUKE32_SCALER_PRAGMA

static __inline int32_t mulscale32(int32_t a, int32_t d)
{
    _asm {
        mov eax, a
            imul d
            mov eax, edx
    }
}

static __inline int32_t dmulscale(int32_t a, int32_t d, int32_t S, int32_t D, int32_t c)
{
    _asm {
        mov ecx, c
            mov eax, a
            imul d
            mov ebx, eax
            mov eax, S
            mov esi, edx
            imul D
            add eax, ebx
            adc edx, esi
            shrd eax, edx, cl
    }
}

static __inline int32_t dmulscale32(int32_t a, int32_t d, int32_t S, int32_t D)
{
    _asm {
        mov eax, a
            imul d
            mov ebx, eax
            mov eax, S
            mov esi, edx
            imul D
            add eax, ebx
            adc edx, esi
            mov eax, edx
    }
}

static __inline int32_t tmulscale32(int32_t a, int32_t d, int32_t b, int32_t c, int32_t S, int32_t D)
{
    _asm {
        mov eax, a
            mov ebx, b
            imul d
            xchg eax, ebx
            mov ecx, c
            xchg edx, ecx
            imul edx
            add ebx, eax
            adc ecx, edx
            mov eax, S
            imul D
            add eax, ebx
            adc edx, ecx
            mov eax, edx
    }
}

#define pragmas_have_clearbuf

static __inline void clearbuf(void *d, int32_t c, int32_t a)
{
    _asm {
        mov edi, d
            mov ecx, c
            mov eax, a
            rep stosd
    }
}

#define pragmas_have_clearbufbyte

static __inline void clearbufbyte(void *d, int32_t c, int32_t a)
{
    _asm {
        mov edi, d
            mov ecx, c
            mov eax, a
            cmp ecx, 4
            jae longcopy
            test cl, 1
            jz preskip
            stosb
        preskip :
        shr ecx, 1
            rep stosw
            jmp endit
        longcopy :
        test edi, 1
            jz skip1
            stosb
            dec ecx
        skip1 :
        test edi, 2
            jz skip2
            stosw
            sub ecx, 2
        skip2 :
              mov ebx, ecx
              shr ecx, 2
              rep stosd
              test bl, 2
              jz skip3
              stosw
          skip3 :
        test bl, 1
            jz endit
            stosb
        endit :
    }
}

#define pragmas_have_copybuf

static __inline void copybuf(const void *s, void *d, int32_t c)
{
    _asm {
        mov esi, s
            mov edi, d
            mov ecx, c
            rep movsd
    }
}

#define pragmas_have_copybufbyte

static __inline void copybufbyte(const void *s, void *d, int32_t c)
{
    _asm {
        mov esi, s
            mov edi, d
            mov ecx, c
            cmp ecx, 4
            jae longcopy
            test cl, 1
            jz preskip
            movsb
        preskip :
        shr ecx, 1
            rep movsw
            jmp endit
        longcopy :
        test edi, 1
            jz skip1
            movsb
            dec ecx
        skip1 :
        test edi, 2
            jz skip2
            movsw
            sub ecx, 2
        skip2 :
              mov ebx, ecx
              shr ecx, 2
              rep movsd
              test bl, 2
              jz skip3
              movsw
          skip3 :
        test bl, 1
            jz endit
            movsb
        endit :
    }
}

#define pragmas_have_copybufreverse

static __inline void copybufreverse(const void *s, void *d, int32_t c)
{
    _asm {
        mov esi, s
            mov edi, d
            mov ecx, c
            shr ecx, 1
            jnc skipit1
            mov al, byte ptr[esi]
            dec esi
            mov byte ptr[edi], al
            inc edi
        skipit1 :
        shr ecx, 1
            jnc skipit2
            mov ax, word ptr[esi-1]
            sub esi, 2
            ror ax, 8
            mov word ptr[edi], ax
            add edi, 2
        skipit2:
        test ecx, ecx
            jz endloop
        begloop :
        mov eax, dword ptr[esi-3]
            sub esi, 4
            bswap eax
            mov dword ptr[edi], eax
            add edi, 4
            dec ecx
            jnz begloop
        endloop :
    }
}

#define pragmas_have_qinterpolatedown16

static __inline void qinterpolatedown16(int32_t a, int32_t c, int32_t d, int32_t s)
{
    _asm {
        mov eax, a
            mov ecx, c
            mov edx, d
            mov esi, s
            mov ebx, ecx
            shr ecx, 1
            jz skipbegcalc
        begqcalc :
        lea edi, [edx+esi]
            sar edx, 16
            mov dword ptr[eax], edx
            lea edx, [edi+esi]
            sar edi, 16
            mov dword ptr[eax+4], edi
            add eax, 8
            dec ecx
            jnz begqcalc
            test ebx, 1
            jz skipbegqcalc2
        skipbegcalc :
        sar edx, 16
            mov dword ptr[eax], edx
        skipbegqcalc2 :
    }
}

static __inline void qinterpolatedown16short(int32_t a, int32_t c, int32_t d, int32_t s)
{
    _asm {
        mov eax, a
            mov ecx, c
            mov edx, d
            mov esi, s
            test ecx, ecx
            jz endit
            test al, 2
            jz skipalignit
            mov ebx, edx
            sar ebx, 16
            mov word ptr[eax], bx
            add edx, esi
            add eax, 2
            dec ecx
            jz endit
        skipalignit :
        sub ecx, 2
            jc finishit
        begqcalc :
        mov ebx, edx
            add edx, esi
            sar ebx, 16
            mov edi, edx
            and edi, 0ffff0000h
            add edx, esi
            add ebx, edi
            mov dword ptr[eax], ebx
            add eax, 4
            sub ecx, 2
            jnc begqcalc
            test cl, 1
            jz endit
        finishit :
        mov ebx, edx
            sar ebx, 16
            mov word ptr[eax], bx
        endit :
    }
}

#define pragmas_have_klabs

static __inline int32_t klabs(int32_t a)
{
    _asm {
        mov eax, a
            test eax, eax
            jns skipnegate
            neg eax
        skipnegate :
    }
}

#define pragmas_have_ksgn

static __inline int ksgn(int32_t b)
{
    _asm {
        mov ebx, b
            add ebx, ebx
            sbb eax, eax
            cmp eax, ebx
            adc al, 0
    }
}

#define pragmas_have_swaps

static __inline void swapchar(void *a, void *b)
{
    _asm {
        mov eax, a
            mov ebx, b
            mov cl, [eax]
            mov ch, [ebx]
            mov[ebx], cl
            mov[eax], ch
    }
}

static __inline void swapshort(void *a, void *b)
{
    _asm {
        mov eax, a
            mov ebx, b
            mov cx, [eax]
            mov dx, [ebx]
            mov[ebx], cx
            mov[eax], dx
    }
}

static __inline void swaplong(void *a, void *b)
{
    _asm {
        mov eax, a
            mov ebx, b
            mov ecx, [eax]
            mov edx, [ebx]
            mov[ebx], ecx
            mov[eax], edx
    }
}

#define swapfloat swaplong

static __inline void swapbuf4(void *a, void *b, int32_t c)
{
    _asm {
        mov eax, a
            mov ebx, b
            mov ecx, c
        begswap :
        mov esi, [eax]
            mov edi, [ebx]
            mov[ebx], esi
            mov[eax], edi
            add eax, 4
            add ebx, 4
            dec ecx
            jnz short begswap
    }
}

static __inline void swap64bit(void *a, void *b)
{
    _asm {
        mov eax, a
            mov ebx, b
            mov ecx, [eax]
            mov edx, [ebx]
            mov[ebx], ecx
            mov ecx, [eax+4]
            mov[eax], edx
            mov edx, [ebx+4]
            mov[ebx+4], ecx
            mov[eax+4], edx
    }
}

#define swapdouble swap64bit

//swapchar2(ptr1,ptr2,xsiz); is the same as:
//swapchar(ptr1,ptr2); swapchar(ptr1+1,ptr2+xsiz);
static __inline void swapchar2(void *a, void *b, int32_t s)
{
    _asm {
        mov eax, a
            mov ebx, b
            mov esi, s
            add esi, ebx
            mov cx, [eax]
            mov dl, [ebx]
            mov[ebx], cl
            mov dh, [esi]
            mov[esi], ch
            mov[eax], dx
    }
}

#define pragmas_have_krecipasm

//0x007ff000 is (11<<13), 0x3f800000 is (127<<23)
static inline int32_t krecipasm(int32_t a)
{
    _asm
    {
        push ebx
            mov eax, a
            mov fpuasm, eax
            fild dword ptr fpuasm
            add eax, eax
            fstp dword ptr fpuasm
            sbb ebx, ebx
            mov eax, fpuasm
            mov ecx, eax
            and eax, 0x007ff000
            shr eax, 10
            sub ecx, 0x3f800000
            shr ecx, 23
            mov eax, dword ptr reciptable[eax]
            sar eax, cl
            xor eax, ebx
            pop ebx
    }
}

//}}}

#endif // pragmas_x86_h_
#endif // pragmas_h_


code:
#pragma once

#ifndef print_h_
#define print_h_

#define BUILDPRINTBUFSIZ 1024

#ifdef HAVE_CXX11_HEADERS

template <typename T>
struct binwrap
{
    T data;
};
template <typename T>
static FORCE_INLINE constexpr binwrap<T> bin(T x)
{
    return binwrap<T>{x};
}
template <typename T>
struct octwrap
{
    T data;
};
template <typename T>
static FORCE_INLINE constexpr octwrap<T> oct(T x)
{
    return octwrap<T>{x};
}
template <typename T>
struct hexwrap
{
    T data;
};
template <typename T>
static FORCE_INLINE constexpr hexwrap<T> hex(T x)
{
    return hexwrap<T>{x};
}
template <typename T>
struct HEXwrap
{
    T data;
};
template <typename T>
static FORCE_INLINE constexpr HEXwrap<T> HEX(T x)
{
    return HEXwrap<T>{x};
}

//FORCE_INLINE constexpr size_t buildprintpiece(void)
//{
//    debug_break();
//    return 0;
//}

template<typename T>
enable_if_t<is_integral<T>::value, size_t> buildprintpiece(char * const buf, T x)
{
    // log_10(2^x) = x * log(2)/log(10) ~= x * 0.30103
    size_t constexpr numdigits = (sizeof(T) * CHAR_BIT + 1) / 3;
    char str[numdigits + 2]; // +2 for '-', '\0'

    char * strptr = str;

    size_t totalChars;
    if (x < 0)
    {
        size_t numChars = logbasenegative<10>(x);
        totalChars = numChars+1;
        *strptr++ = '-';
        strptr[numChars] = '\0';
        do
        {
            DivResult<T> const qr = divrhs<10>(x);
            x = qr.q;
            strptr[numChars-1] = '0' - (char)qr.r;
        }
        while (--numChars);
    }
    else
    {
        size_t numChars = logbase<10>(x);
        totalChars = numChars;
        strptr[numChars] = '\0';
        do
        {
            DivResult<T> const qr = divrhs<10>(x);
            x = qr.q;
            strptr[numChars-1] = '0' + (char)qr.r;
        }
        while (--numChars);
    }

    Bstrcat(buf, str);
    return totalChars;
}

template<typename T>
enable_if_t<is_integral<T>::value, size_t> buildprintpiece(char * const buf, binwrap<T> const x)
{
    make_unsigned_t<T> const data = x.data;
    int constexpr numChars = sizeof(x)*CHAR_BIT;
    char str[numChars+1];
    str[numChars] = '\0';

    for (int p = 0; p < numChars; ++p)
        str[numChars - 1 - p] = '0' + (char)((data >> p) & 1);

    Bstrcat(buf, str);
    return numChars;
}

template<typename T>
enable_if_t<is_integral<T>::value, size_t> buildprintpiece(char * const buf, octwrap<T> const x)
{
    make_unsigned_t<T> const data = x.data;
    int constexpr numChars = (sizeof(x)*CHAR_BIT + 2) / 3;
    char str[numChars+1];
    str[numChars] = '\0';

    for (int p = 0; p < numChars; ++p)
        str[numChars - 1 - p] = '0' + (char)((data >> (p*3)) & 7);

    Bstrcat(buf, str);
    return numChars;
}

template<typename T>
enable_if_t<is_integral<T>::value, size_t> buildprintpiece(char * const buf, hexwrap<T> const x)
{
    static constexpr char const hexletters[] = "0123456789abcdef";
    make_unsigned_t<T> const data = x.data;
    int constexpr numChars = (sizeof(x)*CHAR_BIT + 3) >> 2;
    char str[numChars+1];
    str[numChars] = '\0';

    for (int p = 0; p < numChars; ++p)
        str[numChars - 1 - p] = hexletters[(int)((data >> (p<<2)) & 0xF)];

    Bstrcat(buf, str);
    return numChars;
}

template<typename T>
enable_if_t<is_integral<T>::value, size_t> buildprintpiece(char * const buf, HEXwrap<T> const x)
{
    static constexpr char const HEXletters[] = "0123456789ABCDEF";
    make_unsigned_t<T> const data = x.data;
    int constexpr numChars = (sizeof(x)*CHAR_BIT + 3) >> 2;
    char str[numChars+1];
    str[numChars] = '\0';

    for (int p = 0; p < numChars; ++p)
        str[numChars - 1 - p] = HEXletters[(int)((data >> (p<<2)) & 0xF)];

    Bstrcat(buf, str);
    return numChars;
}

template <typename T>
FORCE_INLINE size_t buildprintpiece(char * const buf, const T * x)
{
    return buildprintpiece(buf, hex((uintptr_t)x));
}

FORCE_INLINE size_t buildprintpiece(char * const buf, char const * const str)
{
    Bstrcat(buf, str);
    return Bstrlen(str);
}

template<typename T>
static FORCE_INLINE size_t buildprint_internal__(char * const buf, T const first)
{
    return buildprintpiece(buf, first);
}

template<typename T, typename... Args>
size_t buildprint_internal__(char * const buf, T const first, Args... args)
{
    size_t const len = buildprintpiece(buf, first);
    return len + buildprint_internal__(buf, args...);
}

template<typename... Args>
size_t buildprint(Args... args)
{
    auto const buf = (char *)Balloca(BUILDPRINTBUFSIZ+1);
    buf[0] = 0;
    size_t const len = buildprint_internal__(buf, args...);

    g_useLogCallback = false;
    LOG_F(INFO, "%s", buf);
    g_useLogCallback = true;

    initputs(buf);

    return len;
}

// this file is incomplete. a fuller implementation exists but has not been completed and debugged.

#endif

#endif // print_h_


code:
// LIGHTS
#ifndef prlight_h_
# define prlight_h_

#define             PR_MAXLIGHTS            1024
#define             PR_MAXPLANELIGHTS       32
#define             SHADOW_DEPTH_OFFSET     30
#define             PR_MAXLIGHTPRIORITY     6

typedef struct      s_prplanelist {
    struct s_prplane*       plane;
    struct s_prplanelist*   n;
}                   _prplanelist;

#pragma pack(push,1)
typedef struct      s_prlight {
    union {
        struct
        {
            int32_t x, y, z;
        };
        vec3_t xyz;
        vec2_t xy;
    };
    int32_t         horiz, range;
    int16_t         angle, faderadius, radius, sector;
    uint8_t         color[3], priority;
    int8_t          minshade, maxshade;
    int16_t         tilenum, owner;
    struct          {
        int         emitshadow  : 1;
        int         negative    : 1;
    }               publicflags;
    // internal members
    float           proj[16];
    float           transform[16];
    float           frustum[5 * 4];
    int32_t         rtindex;
    struct          {
        int         active      : 1;
        int         invalidate  : 1;
        int         isinview    : 1;
    }               flags;
    uint32_t        lightmap;
    _prplanelist*   planelist;
    int32_t         planecount;
}                   _prlight;

extern _prlight     prlights[PR_MAXLIGHTS];
extern int32_t      lightcount;
#pragma pack(pop)

#endif


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.

/* Routines for generation of pseudo-random integer sequences. */

#pragma once

#ifndef random_h
#define random_h

#include "compat.h"

#define WRAND_MAX 32767u

#ifdef engine_c_
int32_t randomseed;
uint32_t wrandomseed = 1;
#else
extern int32_t randomseed;
extern uint32_t wrandomseed;
#endif

#if !KRANDDEBUG
static FORCE_INLINE int32_t krand(void)
{
    randomseed = (randomseed * 1664525ul) + 221297ul;
    return ((uint32_t) randomseed)>>16;
}
#else
int32_t    krand(void);
#endif

static FORCE_INLINE int32_t seed_krand(int32_t* seed)
{
    *seed = (*seed * 1664525ul) + 221297ul;
    return ((uint32_t)*seed) >> 16;
}

// This aims to mimic Watcom C's implementation of rand
static FORCE_INLINE int32_t wrand(void)
{
    wrandomseed = 1103515245 * wrandomseed + 12345;
    return (wrandomseed >> 16) & 0x7FFF;
}

static FORCE_INLINE void wsrand(int seed)
{
    wrandomseed = seed;
}

#endif


code:
#ifndef rawinput_h_
#define rawinput_h_

#include "compat.h"

void RI_PollDevices(BOOL loop);
void RI_ProcessMessage(MSG *msg);
BOOL RI_CaptureInput(BOOL grab, HWND target);

#ifndef VK_LBUTTON
#define VK_LBUTTON        0x01
#endif
#ifndef VK_RBUTTON
#define VK_RBUTTON        0x02
#endif
#ifndef VK_CANCEL
#define VK_CANCEL         0x03
#endif
#ifndef VK_MBUTTON
#define VK_MBUTTON        0x04    /* NOT contiguous with L & RBUTTON */
#endif

#endif // rawinput_h_


code:
/*

  Taken from https://github.com/zpl-c/zpl

  This Software is licensed under the following licenses:

  Unlicense
  This is free and unencumbered software released into the public domain.

  Anyone is free to copy, modify, publish, use, compile, sell, or
  distribute this software, either in source code form or as a compiled
  binary, for any purpose, commercial or non-commercial, and by any
  means.

  In jurisdictions that recognize copyright laws, the author or authors
  of this software dedicate any and all copyright interest in the
  software to the public domain. We make this dedication for the benefit
  of the public at large and to the detriment of our heirs and
  successors. We intend this dedication to be an overt act of
  relinquishment in perpetuity of all present and future rights to this
  software under copyright law.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  OTHER DEALINGS IN THE SOFTWARE.

  For more information, please refer to <http://unlicense.org/>
*/

#ifndef rdtsc_h_
#define rdtsc_h_

#if defined(__GCC__) || defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif

#if defined(__cplusplus)
extern "C" {
#endif

#if defined _MSC_VER && !defined __clang__ && !defined(_M_ARM64)
#define HAVE_TIMER_RDTSC
FORCE_INLINE uint64_t eduke32_rdtsc(void) { return __rdtsc( ); }
#elif defined __i386__
#define HAVE_TIMER_RDTSC
FORCE_INLINE uint64_t eduke32_rdtsc(void) {
    uint64_t x;
    __asm__ volatile(".byte 0x0f, 0x31" : "=A"(x));
    return x;
}
#elif defined __x86_64__
#define HAVE_TIMER_RDTSC
FORCE_INLINE uint64_t eduke32_rdtsc(void) {
    uint32_t hi, lo;
    __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi));
    return ((uint64_t) lo) | (((uint64_t) hi) << 32);
}
#elif defined EDUKE32_CPU_PPC
#define HAVE_TIMER_RDTSC
FORCE_INLINE uint64_t eduke32_rdtsc(void) {
    uint64_t result = 0;
    uint32_t upper, lower, tmp;
    __asm__ volatile("0:                   \n"
                     "\tmftbu   %0         \n"
                     "\tmftb    %1         \n"
                     "\tmftbu   %2         \n"
                     "\tcmpw    %2,%0      \n"
                     "\tbne     0b         \n"
                     : "=r"(upper), "=r"(lower), "=r"(tmp));
    result = upper;
    result = result << 32;
    result = result | lower;

    return result;
}
#elif defined EDUKE32_CPU_ARM
#define HAVE_TIMER_RDTSC
FORCE_INLINE uint64_t eduke32_rdtsc(void) {
#if defined(__aarch64__)
    int64_t r = 0;
    asm volatile("mrs %0, cntvct_el0" : "=r"(r));
#elif (__ARM_ARCH >= 6)
    uint32_t r = 0;
    uint32_t pmccntr;
    uint32_t pmuseren;
    uint32_t pmcntenset;

    // Read the user mode perf monitor counter access permissions.
    asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r"(pmuseren));
    if (pmuseren & 1) { // Allows reading perfmon counters for user mode code.
        asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcntenset));
        if (pmcntenset & 0x80000000ul) { // Is it counting?
            asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(pmccntr));
            // The counter is set up to count every 64th cycle
            return ((int64_t)pmccntr) * 64; // Should optimize to << 6
        }
    }
#else
#error "No rdtsc implementation defined for this architecture."
#endif
    return r;
}
#endif

#if defined(__cplusplus)
}
#endif

#if defined(__GCC__) || defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic pop
#endif

#endif /* rdtsc_h_ */


code:
#ifdef RENDERTYPEWIN
# include "winlayer.h"
#else
# include "sdlayer.h"
#endif

#undef STARTUP_SETUP_WINDOW

#ifdef STARTUP_WINDOW
#if defined _WIN32 || defined EDUKE32_OSX || defined HAVE_GTK2
# define STARTUP_SETUP_WINDOW
#endif
#endif

#undef WM_MSGBOX_WINDOW
#if defined _WIN32 || defined EDUKE32_OSX || defined HAVE_GTK2 || (defined RENDERTYPESDL && SDL_MAJOR_VERSION >= 2)
# define WM_MSGBOX_WINDOW
#endif


code:
#pragma once

#ifndef rev_h__
#define rev_h__

#if defined REV
# define REV__(x) #x
# define REV_(x) REV__(x)
# define REVSTR REV_(REV)
#else
# define REVSTR "r(?)"
# define EDUKE32_UNKNOWN_REVISION
#endif
#endif // rev_h__


code:
#define  sc_None         0
#define  sc_Bad          0xff
#define  sc_Comma        0x33
#define  sc_Period       0x34
#define  sc_Return       0x1c
#define  sc_Enter        sc_Return
#define  sc_Escape       0x01
#define  sc_Space        0x39
#define  sc_BackSpace    0x0e
#define  sc_Tab          0x0f
#define  sc_LeftAlt      0x38
#define  sc_LeftControl  0x1d
#define  sc_CapsLock     0x3a
#define  sc_LeftShift    0x2a
#define  sc_RightShift   0x36
#define  sc_F1           0x3b
#define  sc_F2           0x3c
#define  sc_F3           0x3d
#define  sc_F4           0x3e
#define  sc_F5           0x3f
#define  sc_F6           0x40
#define  sc_F7           0x41
#define  sc_F8           0x42
#define  sc_F9           0x43
#define  sc_F10          0x44
#define  sc_F11          0x57
#define  sc_F12          0x58
#define  sc_Kpad_Star    0x37
#define  sc_Pause        0x59
#define  sc_ScrollLock   0x46
#define  sc_NumLock      0x45
#define  sc_Slash        0x35
#define  sc_SemiColon    0x27
#define  sc_Quote        0x28
#define  sc_Tilde        0x29
#define  sc_BackSlash    0x2b

#define  sc_OpenBracket  0x1a
#define  sc_CloseBracket 0x1b

#define  sc_1            0x02
#define  sc_2            0x03
#define  sc_3            0x04
#define  sc_4            0x05
#define  sc_5            0x06
#define  sc_6            0x07
#define  sc_7            0x08
#define  sc_8            0x09
#define  sc_9            0x0a
#define  sc_0            0x0b
#define  sc_Minus        0x0c
#define  sc_Equals       0x0d
#define  sc_Plus         0x0d

#define  sc_kpad_1       0x4f
#define  sc_kpad_2       0x50
#define  sc_kpad_3       0x51
#define  sc_kpad_4       0x4b
#define  sc_kpad_5       0x4c
#define  sc_kpad_6       0x4d
#define  sc_kpad_7       0x47
#define  sc_kpad_8       0x48
#define  sc_kpad_9       0x49
#define  sc_kpad_0       0x52
#define  sc_kpad_Minus   0x4a
#define  sc_kpad_Plus    0x4e
#define  sc_kpad_Period  0x53

#define  sc_A            0x1e
#define  sc_B            0x30
#define  sc_C            0x2e
#define  sc_D            0x20
#define  sc_E            0x12
#define  sc_F            0x21
#define  sc_G            0x22
#define  sc_H            0x23
#define  sc_I            0x17
#define  sc_J            0x24
#define  sc_K            0x25
#define  sc_L            0x26
#define  sc_M            0x32
#define  sc_N            0x31
#define  sc_O            0x18
#define  sc_P            0x19
#define  sc_Q            0x10
#define  sc_R            0x13
#define  sc_S            0x1f
#define  sc_T            0x14
#define  sc_U            0x16
#define  sc_V            0x2f
#define  sc_W            0x11
#define  sc_X            0x2d
#define  sc_Y            0x15
#define  sc_Z            0x2c

// Extended scan codes

#define  sc_UpArrow      0xc8 //0x5a
#define  sc_DownArrow    0xd0 //0x6a
#define  sc_LeftArrow    0xcb //0x6b
#define  sc_RightArrow   0xcd //0x6c
#define  sc_Insert       0xd2 //0x5e
#define  sc_Delete       0xd3 //0x5f
#define  sc_Home         0xc7 //0x61
#define  sc_End          0xcf //0x62
#define  sc_PgUp         0xc9 //0x63
#define  sc_PgDn         0xd1 //0x64
#define  sc_RightAlt     0xb8 //0x65
#define  sc_RightControl 0x9d //0x66
#define  sc_kpad_Slash   0xb5 //0x67
#define  sc_kpad_Enter   0x9c //0x68
#define  sc_PrintScreen  0xb7 //0x69
#define  sc_LeftWin      0xdb
#define  sc_RightWin     0xdc
//#define  sc_LastScanCode 0x6e

// Ascii scan codes

#define asc_Enter 13
#define asc_Escape 27
#define asc_Ctrl_A 1
#define asc_Ctrl_B 2
#define asc_Ctrl_C 3
#define asc_Ctrl_E 5
#define asc_Ctrl_F 6
#define asc_BackSpace 8
#define asc_Tab 9
#define asc_Ctrl_K 11
#define asc_Ctrl_L 12
#define asc_Ctrl_N 14
#define asc_Ctrl_P 16
#define asc_Ctrl_U 21
#define asc_Ctrl_W 23
#define asc_Space 32


code:
#pragma once

#ifndef screenshot_h__
#define screenshot_h__

extern char screenshot_dir[BMAX_PATH];

int videoCaptureScreen(const char* filename, char inverseit) ATTRIBUTE((nonnull(1)));
int videoCaptureScreenTGA(const char* filename, char inverseit) ATTRIBUTE((nonnull(1)));

#endif // screenshot_h__


code:
/*
 * screentext.h
 *
 * Copyright © 2020, Evan Ramos. All rights reserved.
 */

#ifndef SCREENTEXT_H_
#define SCREENTEXT_H_
#pragma once

#include "compat.h"

#ifdef __cplusplus
extern "C" {
#endif

static inline CONSTEXPR_CXX14 size_t utf8len(char const * s)
{
    size_t len = 0;
    char c = '\0';
    while ((c = *s) != '\0')
    {
        len += ((c & 0xC0) != 0x80);
        ++s;
    }
    return len;
}

static inline CONSTEXPR_CXX14 size_t utf8charbytes(char c)
{
    if ((c & 0xF8) == 0xF0)
        return 4;
    else if ((c & 0xF0) == 0xE0)
        return 3;
    else if ((c & 0xE0) == 0xC0)
        return 2;

    return 1;
}

typedef uint16_t ScreenTextGlyph_t;

enum ScreenTextSentinels : ScreenTextGlyph_t
{
    SCREENTEXT_CONTROLCODE = 1u<<15u,

    SCREENTEXT_PALCHANGE   = SCREENTEXT_CONTROLCODE | 1u<<14u,
    SCREENTEXT_CONSTWIDTH  = SCREENTEXT_CONTROLCODE | 1u<<13u,

    SCREENTEXT_NEWLINE     = SCREENTEXT_CONTROLCODE | 1u<<12u,
    SCREENTEXT_SPACE       = SCREENTEXT_CONTROLCODE | 1u<<11u,
    SCREENTEXT_TAB         = SCREENTEXT_CONTROLCODE | 1u<<10u,
};

static inline int screentextGlyphIsControlCode(ScreenTextGlyph_t g)
{
  return (g & SCREENTEXT_CONTROLCODE);
}
static inline ScreenTextGlyph_t screentextGlyphGetTile(ScreenTextGlyph_t g)
{
  return (g & ~SCREENTEXT_CONTROLCODE);
}

static inline int screentextGlyphIsPalChange(ScreenTextGlyph_t g)
{
  return (g & SCREENTEXT_PALCHANGE) == SCREENTEXT_PALCHANGE;
}
static inline uint8_t screentextGlyphGetPalChange(ScreenTextGlyph_t g)
{
  return (g & 0xFFu);
}
static inline int screentextGlyphIsConstWidth(ScreenTextGlyph_t g)
{
  return (g & SCREENTEXT_CONSTWIDTH) == SCREENTEXT_CONSTWIDTH;
}

static inline int screentextGlyphIsNewline(ScreenTextGlyph_t g)
{
  return (g & SCREENTEXT_NEWLINE) == SCREENTEXT_NEWLINE;
}
static inline int screentextGlyphIsSpace(ScreenTextGlyph_t g)
{
  return (g & SCREENTEXT_SPACE) == SCREENTEXT_SPACE;
}
static inline int screentextGlyphIsTab(ScreenTextGlyph_t g)
{
  return (g & SCREENTEXT_TAB) == SCREENTEXT_TAB;
}

#define TEXT_XRIGHT           (0x00000001)
#define TEXT_XCENTER          (0x00000002)
#define TEXT_YBOTTOM          (0x00000004)
#define TEXT_YCENTER          (0x00000008)

#define TEXT_XOFFSETZERO      (0x00000100)
#define TEXT_XJUSTIFY         (0x00000200)
#define TEXT_YOFFSETZERO      (0x00000400)
#define TEXT_YJUSTIFY         (0x00000800)

#define TEXT_VARHEIGHT        (0x00800000)

struct ScreenTextSize_t
{
    ScreenTextGlyph_t const * text;
    uint32_t len;
    vec2_t pos;
    vec2_t empty, between;
    int32_t constwidth;
    vec2_t b1, b2;
    int32_t zoom, o, f;
    int16_t font, blockangle;
};

struct ScreenText_t
{
    union
    {
        ScreenTextSize_t size;
        struct
        {
            ScreenTextGlyph_t const * text;
            uint32_t len;
            vec2_t pos;
            vec2_t empty, between;
            int32_t constwidth;
            vec2_t b1, b2;
            int32_t zoom, o, f;
            int16_t font, blockangle;
        };
    };
    int32_t standardhalfheight;
    int32_t alpha;
    int16_t charangle;
    int8_t shade;
    uint8_t pal;
};

vec2_t screentextGetSize(ScreenTextSize_t const &);
vec2_t screentextRender(ScreenText_t const &);
vec2_t screentextRenderShadow(ScreenText_t const &, vec2_t, int32_t);

struct TileFontPtr_t
{
    void * opaque;
};

static FORCE_INLINE uint32_t tilefontGetChr32FromASCII(char c)
{
    uint32_t chr32 = 0;
    memcpy(&chr32, &c, sizeof(char));
    return chr32;
}

TileFontPtr_t tilefontGetPtr(uint16_t tilenum);
TileFontPtr_t tilefontFind(uint16_t tilenum);
void tilefontDefineMapping(TileFontPtr_t tilefontPtr, uint32_t chr, uint16_t tilenum);
void tilefontMaybeDefineMapping(TileFontPtr_t tilefontPtr, uint32_t chr, uint16_t tilenum);
uint16_t tilefontLookup(TileFontPtr_t tilefontPtr, uint32_t chr);

struct LocalePtr_t
{
    void * opaque;
};

LocalePtr_t localeGetPtr(const char * localeName);
void localeDefineMapping(LocalePtr_t localePtr, const char * key, const char * val);
void localeMaybeDefineMapping(LocalePtr_t localePtr, const char * key, const char * val);
void localeSetCurrent(const char * localeName);
const char * localeGetCurrent(void);
const char ** localeGetKeys(int32_t& localeCount);
const char * localeLookup(const char * str);

#ifdef __cplusplus
}
#endif

#endif


code:
#ifndef BUILD_SCRIPTFILE_H_
#define BUILD_SCRIPTFILE_H_

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
	char *textbuf;
	uint32_t textlength;
	char *ltextptr;		// pointer to start of the last token fetched (use this for line numbers)
	char *textptr;
	char *eof;
	char *filename;
	int32_t linenum;
	int32_t *lineoffs;
} scriptfile;

char *scriptfile_gettoken(scriptfile *sf);
int32_t scriptfile_getnumber(scriptfile *sf, int32_t *num);
int32_t scriptfile_getdouble(scriptfile *sf, double *num);
int32_t scriptfile_getstring(scriptfile *sf, char **st);
int scriptfile_getsymbol(scriptfile *sf, int32_t *num);
int32_t scriptfile_getlinum(const scriptfile *sf, const char *ptr);
int32_t scriptfile_getbraces(scriptfile *sf, char **braceend);

scriptfile *scriptfile_fromfile(const char *fn);
scriptfile *scriptfile_fromstring(const char *string);
void scriptfile_close(scriptfile *sf);
int scriptfile_eof(scriptfile *sf);

int32_t scriptfile_getsymbolvalue(char const *name, int32_t *val);
int32_t scriptfile_addsymbolvalue(char const *name, int32_t val);
void scriptfile_clearsymbols(void);

#ifdef __cplusplus
}
#endif

#endif


code:
#ifndef SDL_INC_H_
#define SDL_INC_H_

// include this before SDL does
#ifdef _WIN32
# include "windows_inc.h"
#endif

// Workaround for i686-MinGW-w64.
#if defined __MINGW64_VERSION_MAJOR && !defined __MINGW64__
# define __MINGW64_VERSION_MAJOR_BACKUP __MINGW64_VERSION_MAJOR
# undef __MINGW64_VERSION_MAJOR
#endif

#if defined SDL_USEFOLDER
# if SDL_TARGET == 2
#  include <SDL2/SDL.h>
#  include <SDL2/SDL_syswm.h>
# else
#  include <SDL/SDL.h>
#  include <SDL/SDL_syswm.h>
# endif
#else
# include "SDL.h"
# if !defined __APPLE__
#  include "SDL_syswm.h"
# endif
#endif

#if defined __MINGW64_VERSION_MAJOR_BACKUP && !defined __MINGW64__
# define __MINGW64_VERSION_MAJOR __MINGW64_VERSION_MAJOR_BACKUP
# undef __MINGW64_VERSION_MAJOR_BACKUP
#endif

/* =================================================================
Minimum required SDL versions:
=================================================================== */

#define SDL_MIN_X	1
#define SDL_MIN_Y	2
#define SDL_MIN_Z	10
#define SDL_REQUIREDVERSION	(SDL_VERSIONNUM(SDL_MIN_X,SDL_MIN_Y,SDL_MIN_Z))

#define SDL2_MIN_X  2
#define SDL2_MIN_Y  0
#define SDL2_MIN_Z  5
#define SDL2_REQUIREDVERSION (SDL_VERSIONNUM(SDL2_MIN_X,SDL2_MIN_Y,SDL2_MIN_Z))

#if !(SDL_VERSION_ATLEAST(SDL_MIN_X,SDL_MIN_Y,SDL_MIN_Z))
#error SDL version found is too old
#endif

#endif	/* SDL_INC_H_ */


code:
struct sdlappicon {
	Sint32 width,height;
	Uint8 *pixels;
};


code:
// SDL interface layer
// for the Build Engine
// by Jonathon Fowler (jf@jonof.id.au)

#ifndef build_interface_layer_
#define build_interface_layer_ SDL

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

#define EDUKE32_SDL_LINKED_PREREQ(x, a, b, c) ((x).major > (a) || ((x).major == (a) && ((x).minor > (b) || ((x).minor == (b) && (x).patch >= (c)))))

extern int32_t maxrefreshfreq;

#ifdef _WIN32
HWND win_gethwnd(void);
HINSTANCE win_gethinstance(void);
#endif

#include "sdlappicon.h"

#if (SDL_MAJOR_VERSION < 2 && SDL_MINOR_VERSION < 3) // SDL 1.2
int32_t SDL_WaitEventTimeout(SDL_Event *event, int32_t timeout);
#endif

#define SDL_GL_ATTRIBUTES(iter, attrib)                                                                                \
    for (iter = 0; iter < (int32_t)ARRAY_SIZE(attrib); iter++)                                                         \
    {                                                                                \
        int32_t j = attrib[iter].value;                                                                                \
        SDL_GL_SetAttribute(attrib[iter].attr, j);                                                                     \
    }

#define SDL_ADDMODE(x, y, c, f)                                                                                \
    {                                                                                \
        int fullscreen;                                                                                \
        for (fullscreen = f; fullscreen >= 0; --fullscreen)                                                            \
        {                                                                                \
            if (validmodecnt < MAXVALIDMODES)                                                                          \
            {                                                                                \
                int32_t mn;                                                                                \
                for (mn = 0; mn < validmodecnt; mn++)                                                                  \
                    if (validmode[mn].xdim == x && validmode[mn].ydim == y && validmode[mn].bpp == c &&                \
                        validmode[mn].fs == fullscreen)                                                                \
                        break;                                                                                \
                if (mn == validmodecnt)                                                                                \
                {                                                                                \
                    validmode[validmodecnt].xdim = x;                                                                  \
                    validmode[validmodecnt].ydim = y;                                                                  \
                    validmode[validmodecnt].bpp = c;                                                                   \
                    validmode[validmodecnt].fs = fullscreen;                                                           \
                    validmodecnt++;                                                                                \
                    /*initprintf("  - %dx%d %d-bit %s\n", x, y, c, (fullscreen&1)?"fullscreen":"windowed");*/          \
                }                                                                                \
            }                                                                                \
        }                                                                                \
    }

#define SDL_CHECKMODE(w, h) ((w < MAXXDIM) && (h < MAXYDIM) && (w >= MINXDIM) && (h >= MINYDIM) && (((float)w/(float)h) >= 1.2f))

#define SDL_CHECKFSMODES(w, h)                                                                                \
    if (w == 0 && h == 0)                                                                                \
    {                                                                                \
        initprintf("No fullscreen modes available!\n");                                                                \
        w = MAXXDIM;                                                                                \
        h = MAXYDIM;                                                                                \
    }

#if SDL_MAJOR_VERSION >= 2
#define SDL2_VIDEO_ERR(XX)                                                                                \
    {                                                                                \
        initprintf("Unable to set video mode: " XX " failed: %s\n", SDL_GetError());                                   \
        destroy_window_resources();                                                                                \
        return -1;                                                                                \
    }
#endif

static inline void idle_waitevent_timeout(uint32_t timeout)
{
    SDL_WaitEventTimeout(NULL, timeout);
}

static inline void idle_waitevent(void)
{
    SDL_WaitEvent(NULL);
}

static inline void idle(int const msec = 1)
{
#ifdef _WIN32
    Sleep(msec);
#else
    timespec req = { 0, msec * 1000000 };
    do { } while (nanosleep(&req, &req));
#endif
}

#else
#if (build_interface_layer_ != SDL)
#error "Already using the " build_interface_layer_ ". Can't now use SDL."
#endif
#endif // build_interface_layer_