view src/dmlib.h @ 1785:86d10d5d4915

Fix case where DMGrowBuf is growing backwards and needs to be reallocated in dmGrowBufRealloc() and the data is moved to the "end" of the newly grown buffer. Previously we used clrsize as data size, but that is (in retrospect) obviously incorrect. Use old buffer size instead.
author Matti Hamalainen <ccr@tnsp.org>
date Wed, 13 Jun 2018 01:39:06 +0300
parents dcc48679a89e
children ca9fe688ab6b
line wrap: on
line source

/*
 * DMLib
 * -- Main header file
 * Programmed and designed by Matti 'ccr' Hamalainen
 * (C) Copyright 2011-2018 Tecnic Software productions (TNSP)
 */
#ifndef DMLIB_H
#define DMLIB_H

#include <SDL_config.h>
#include <SDL_endian.h>
#include <SDL_types.h>
#include <SDL_mutex.h>
#include <SDL_thread.h>
#include <SDL_video.h>
#include <SDL_render.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>


#ifdef DM_USE_ASSERTS
#  include <assert.h>
#else
#  define assert(NEXPR) // stub
#endif


// Check for arch bitness
#if defined(__WIN64) || defined(_WIN64) || defined(_WIN32) || defined(__WIN32)
#  define DM_WINDOWS 1
#  if defined(__MINGW32__) || defined(__MINGW64__)
#     define __USE_MINGW_ANSI_STDIO 1
#  endif
#endif

#if !defined(DM_ARCH)
#  if defined(__LP64__) || defined(_LP64)
#    define DM_ARCH 64
#  else
#    define DM_ARCH 32
#  endif
#endif

#if !defined(DM_ARCH) && (defined(__WIN64) || defined(_WIN64))
#  define DM_ARCH 64
#endif

#if !defined(DM_ARCH) && (defined(__WIN32) || defined(_WIN32))
#  define DM_ARCH 32
#endif


// Do we have a valid arch?
// If so, set some printf specifiers
#if DM_ARCH == 32
#  define DM_PRIu32        "u"
#  define DM_PRId32        "d"
#  define DM_PRIx32        "x"
#  ifdef DM_WINDOWS
#    define DM_PRIu64      "u"
#    define DM_PRId64      "d"
#    define DM_PRIx64      "x"
#  else
#    define DM_PRIu64      "llu"
#    define DM_PRId64      "lld"
#    define DM_PRIx64      "llx"
#  endif
#  define DM_PRIu_SIZE_T   "u"
#  define DM_PRId_SSIZE_T  "d"
#  define DM_PRIx_SIZE_T   "x"
#elif DM_ARCH == 64
#  define DM_PRIu32        "u"
#  define DM_PRId32        "d"
#  define DM_PRIx32        "x"
#  define DM_PRIu64        "lu"
#  define DM_PRId64        "ld"
#  define DM_PRIx64        "lx"
#  define DM_PRIu_SIZE_T   "lu"
#  define DM_PRId_SSIZE_T  "ld"
#  define DM_PRIx_SIZE_T   "lx"
#else
#  error Could not determine architecture (32/64bit), please define DM_ARCH=32 or 64
#endif


#ifdef __cplusplus
extern "C" {
#endif

// Defaults
#define DM_PROG_AUTHOR      "By Matti 'ccr' Hamalainen (C) Copyright 2018 TNSP"
#define DM_PROG_LICENSE     "Et all, see README / COPYING for more information."

/* Error codes
 */
enum {
    // General error codes
    DMERR_OK = 0,
    DMERR_PROGRESS,     // Status OK, but operation in progress

    DMERR_INTERNAL,
	
    DMERR_FOPEN,
    DMERR_FREAD,
    DMERR_FWRITE,
    DMERR_FSEEK,
    DMERR_NOT_FOUND,    // Resource/data not found

    DMERR_INVALID_DATA, // Some data was invalid
    DMERR_MALLOC,       // Memory allocation failure
    DMERR_ALREADY_INIT, // Resource has already been initialized
    DMERR_INIT_FAIL,    // General initialization failure
    DMERR_INVALID_ARGS,

    DMERR_NULLPTR,      // NULL pointer specified in critical argument
    DMERR_NOT_SUPPORTED,// Operation not supported
    DMERR_OUT_OF_DATA,
    DMERR_EXTRA_DATA,
    DMERR_BOUNDS,

    DMERR_DATA_ERROR,   // Data decoding/encoding/parsing error
    
    DMERR_VERSION,      // Unsupported data version

    // PACK-file subsystem
    DMERR_NOTPACK,
    DMERR_PACK_VERSION,
    DMERR_INVALID,
    DMERR_COMPRESSION,
};


// Directory/path separator stuff
#define DM_DIR_SEPARATOR     '/'


// Resource management defines
#define DMRES_NAME_LEN  32
#define DMRES_DATA_PACK	"data.pak"  // Name of the data-file
#define DMRES_DATA_PATH	"data/"     // Sub-directory path
#define DMRES_RES_FILE  "res.txt"   // Resource data file


/* Define a boolean type
 */
#if !defined(FALSE) && !defined(TRUE) && !defined(BOOL)
typedef enum { FALSE = 0, TRUE = 1 } BOOL;
#endif

#ifndef BOOL
#  ifdef bool
#    define BOOL bool
#  else
#    define BOOL int
#  endif
#endif


/* Math constants
 */
#define DM_PI   3.14159265358f
#define DM_PI2  6.28318530718f
#define DM_E    2.71828182846f


/* Fixed point math types
 */
typedef union
{
    Sint64 dw;
    Sint32 w[2];
} DMFixedPoint;


typedef union
{
    Sint32 dw;
    Sint16 w[2];
} DMFixedPoint32;


/* Macros for fixed point math
 */
#define FP_SET(a, k) a.dw = k ## ULL
#define FP_CONV(a, k) a.dw = (k)

#ifndef SDL_BYTEORDER
#  error Undefined byteorder!
#endif

#if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
#  define FP_SETH(a, k) a.w[0] = (k)
#  define FP_SETL(a, k) a.w[1] = (k)
#  define FP_SETHL(a, h, l) { a.w[0] = (h); a.w[1] = (l); }
#  define FP_GETH32(a) a.w[0]
#  define FP_GETL32(a) a.w[1]
#  define FP_GETH16(a) a.w[0]
#  define FP_GETL16(a) a.w[1]
#elif (SDL_BYTEORDER == SDL_LIL_ENDIAN)
#  define FP_SETH(a, k) a.w[1] = (k)
#  define FP_SETL(a, k) a.w[0] = (k)
#  define FP_SETHL(a, h, l) { a.w[1] = (h); a.w[0] = (l); }
#  define FP_GETH32(a) a.w[1]
#  define FP_GETL32(a) a.w[0]
#  define FP_GETH16(a) a.w[1]
#  define FP_GETL16(a) a.w[0]
#else
#  error Unsupported byte order!
#endif

#define FP_PRINTF64(a) printf("%.8x:%.8x", FP_GETH32(a), FP_GETL32(a))
#define FP_PRINTF32(a) printf("%.4x:%.4x", FP_GETH16(a), FP_GETL16(a))

#define FP_ADD(a, b) a.dw += b.dw
#define FP_SUB(a, b) a.dw -= b.dw
#define FP_ADD_R(r, a, b) r.dw = a.dw + b.dw
#define FP_SUB_R(r, a, b) r.dw = a.dw - b.dw
#define FP_DIV(a, b) a.dw /= b.dw
#define FP_MUL(a, b) a.dw *= b.dw
#define FP_DIV_R(r, a, b) r.dw = (a.dw / b.dw)
#define FP_MUL_R(r, a, b) r.dw = (a.dw * b.dw)


/* Miscellaneous types
 */
typedef struct
{
#if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
    Uint8 a,g,b,r;
#elif (SDL_BYTEORDER == SDL_LIL_ENDIAN)
    Uint8 r,g,b,a;
#endif
} DMColor;


typedef float DMFloat;


// Macro for swapping two lvalues of same type
#define DM_SWAP(T, A, B) { if ((B) < (A)) { T swtmp = (B); B = (A); A = swtmp; } }


/* Drawing modes used by blitting and some other functions.
 */
enum
{
    DMD_NONE        = 0x0000,
    DMD_TRANSPARENT = 0x0001,
    DMD_SATURATE    = 0x0002,

    DMD_ANTIALIAS   = 0x0004,

    DMD_NMODES      = 6
};


// Available bitdepths. Not all functions may support every one of these.
enum
{
    DMD_8BIT = 0,
    DMD_32BIT,

    DMD_NBITDEPTHS
};


static inline int dmBitsPerPixel2Index(int bpp)
{
    return (bpp == 8 ? 0 : (bpp == 32 ? 1 : -1));
}


static inline DMFloat dmClamp10(const DMFloat a)
{
    return (a < 0.0f ? 0.0f : (a > 1.0f ? 1.0f : a));
}


static inline int dmClamp(const int v, const int min, const int max)
{
    return (v < min ? min : (v > max ? max : v));
}


/* Arbitrary line drawing
 */
#ifdef DM_GFX_LINES
#define DM_HEADER
#include "dmlinefunc.h"

enum
{
    CLIP_TOP     = 1,
    CLIP_BOTTOM  = 2,
    CLIP_RIGHT   = 4,
    CLIP_LEFT    = 8
};

#define DM_CLIP_FUNC dmClipLineCoordsFloat
#define DM_COORD_TYPE DMFloat
#include "dmlineclip.h"

#undef DM_HEADER
#endif


/* Various blitting functions
 */
#ifdef DM_GFX_BLITS
typedef int (*DMScaledBlitFunc)(SDL_Surface *src, const int x0, const int y0, const int dwidth, const int dheight, SDL_Surface *dst);
DMScaledBlitFunc dmGetScaledBlitFunc(SDL_PixelFormat *src, SDL_PixelFormat *dst, int mode);
int dmScaledBlitSurfaceAny(SDL_Surface *src, const int x0, const int y0, const int dwidth, const int dheight, SDL_Surface *dst, int mode);

typedef int (*DMUnscaledBlitFunc)(SDL_Surface *src, const int x0, const int y0, SDL_Surface *dst);
DMUnscaledBlitFunc dmGetUnscaledBlitFunc(SDL_PixelFormat *src, SDL_PixelFormat *dst, int mode);
int dmUnscaledBlitSurfaceAny(SDL_Surface *src, const int x0, const int y0, SDL_Surface *dst, int mode);

SDL_Surface *dmConvertScaledSurface(SDL_Surface *src, SDL_PixelFormat *fmt, const int dwidth, const int dheight);


#define DM_HEADER
#include "dmblitfunc.h"
#undef DM_HEADER

#endif // DM_GFX_BLITS


static inline void dmClearSurface(SDL_Surface *screen, const Uint32 col)
{
    SDL_FillRect(screen, NULL, col);
}


static inline Uint32 dmMapRGB(SDL_Surface *screen, int r, int g, int b)
{
    return SDL_MapRGB(screen->format, r, g, b);
}


static inline Uint32 dmMapRGBA(SDL_Surface *screen, int r, int g, int b, int a)
{
    return SDL_MapRGBA(screen->format, r, g, b, a);
}


static inline int dmDirectBlitSurface(SDL_Surface *bmp, SDL_Surface *screen)
{
    return SDL_BlitSurface(bmp, NULL, screen, NULL);
}


static inline SDL_Surface *dmCopySurface(SDL_Surface *src)
{
    if (src != NULL)
        return SDL_ConvertSurface(src, src->format, src->flags);
    else
        return NULL;
}


/* Global variables
 */
extern char *dmProgName,
            *dmProgDesc,
            *dmProgVersion,
            *dmProgAuthor,
            *dmProgLicense;

extern int dmVerbosity;
void       dmInitProg(char *name, char *desc, char *version, char *author, char *license);
void       dmPrintBanner(FILE *outFile, const char *name, const char *usage);

void       dmMsgVA(int level, const char *fmt, va_list ap);
void       dmMsg(int level, const char *fmt, ...);
void       dmPrintVA(int level, const char *fmt, va_list ap);
void       dmPrint(int level, const char *fmt, ...);

int        dmErrorVA(const int error, const char *fmt, va_list);
int        dmError(const int error, const char *fmt, ...);
void       dmErrorMsg(const char *fmt, ...);
int        dmGetErrno();
const char *dmErrorStr(const int error);

#ifdef DM_DEBUG
#    define dmErrorDBG dmError
#    define dmErrorDBGMsg dmErrorMsg
#else
#    define dmErrorDBG(ecode, fmt, ...) (ecode) // Dummy
#    define dmErrorDBGMsg(fmt, ...)
#endif

void *     dmMalloc(size_t len);
void *     dmMalloc0(size_t len);
void *     dmRealloc(void *ptr, size_t len);
void *     dmCalloc(size_t n, size_t len);
void       dmFree(void *ptr);
void       dmFreeRReal(void **ptr);
#define    dmFreeR(ptr) dmFreeRReal((void **) ptr)

#if defined(DM_HAVE_MEMSET) || defined(DM_HAVE_STRING_H)
static inline void * dmMemset(void *ptr, const int c, size_t n)
{
    return memset(ptr, c, n);
}
#else
void *     dmMemset(void *ptr, const int c, size_t n);
#endif

char *     dm_strdup(const char *);
char *     dm_strndup(const char *, const size_t n);
char *     dm_strdup_vprintf(const char *, va_list);
char *     dm_strdup_printf(const char *, ...);

char *     dm_basefilename(const char *filename);
char *     dm_strdup_fext(const char *filename, const char *fmt);
char *     dm_strrcasecmp(char *str, const char *needle);

BOOL       dmGetIntVal(const char *s, unsigned int *i);


/* Mutexes
 */
#ifdef DM_MUTEX_DEBUG

typedef struct
{
    BOOL used;
    Uint32 id;
    int state;
} DMMutexLock;

typedef struct
{
    char *cr_file;
    int cr_line;
    SDL_mutex *m;
    DMMutexLock locks[8];
} DMMutex;

#define dmMutexLock(x) dmDOMutexLock(x, __FILE__, (int) __LINE__)
#define dmMutexUnlock(x) dmDOMutexUnlock(x, __FILE__, (int) __LINE__)
#define dmCreateMutex(x) dmDOCreateMutex(__FILE__, (int) __LINE__)

int        dmDOMutexLock(DMMutex *mutex, const char *file, const int line);
int        dmDOMutexUnlock(DMMutex *mutex, const char *file, const int line);
DMMutex *  dmDOCreateMutex(const char *file, const int line);
void       dmDestroyMutex(DMMutex *mutex);

#else
#define DMMutex SDL_mutex
#define dmCreateMutex() SDL_CreateMutex()
#define dmDestroyMutex(x) SDL_DestroyMutex(x)
#define dmMutexLock(x) SDL_mutexP(x)
#define dmMutexUnlock(x) SDL_mutexV(x)
#endif

/* Endianess swapping macros
 */
#define DM_SWAP_16_LE_BE(value) ((Uint16) ( \
    (Uint16) ((Uint16) (value) >> 8) |      \
    (Uint16) ((Uint16) (value) << 8)) )


#define DM_SWAP_32_LE_BE(value) ((Uint32) (             \
    (((Uint32) (value) & (Uint32) 0x000000ffU) << 24) | \
    (((Uint32) (value) & (Uint32) 0x0000ff00U) <<  8) | \
    (((Uint32) (value) & (Uint32) 0x00ff0000U) >>  8) | \
    (((Uint32) (value) & (Uint32) 0xff000000U) >> 24)))

#define DM_SWAP_64_LE_BE(value) ((Uint64) (                       \
    (((Uint64) (value) & (Uint64) 0x00000000000000ffULL) << 56) | \
    (((Uint64) (value) & (Uint64) 0x000000000000ff00ULL) << 40) | \
    (((Uint64) (value) & (Uint64) 0x0000000000ff0000ULL) << 24) | \
    (((Uint64) (value) & (Uint64) 0x00000000ff000000ULL) <<  8) | \
    (((Uint64) (value) & (Uint64) 0x000000ff00000000ULL) >>  8) | \
    (((Uint64) (value) & (Uint64) 0x0000ff0000000000ULL) >> 24) | \
    (((Uint64) (value) & (Uint64) 0x00ff000000000000ULL) >> 40) | \
    (((Uint64) (value) & (Uint64) 0xff00000000000000ULL) >> 56)))


/* Macros that swap only when needed ...
 */
#if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
#  define DM_LE16_TO_NATIVE(value) DM_SWAP_16_LE_BE(value)
#  define DM_LE32_TO_NATIVE(value) DM_SWAP_32_LE_BE(value)
#  define DM_NATIVE_TO_LE16(value) DM_SWAP_16_LE_BE(value)
#  define DM_NATIVE_TO_LE32(value) DM_SWAP_32_LE_BE(value)

#  define DM_BE16_TO_NATIVE(value) ((Uint16) (value))
#  define DM_BE32_TO_NATIVE(value) ((Uint32) (value))
#  define DM_NATIVE_TO_BE16(value) ((Uint16) (value))
#  define DM_NATIVE_TO_BE32(value) ((Uint32) (value))

#  define DM_LE64_TO_NATIVE(value) DM_SWAP_64_LE_BE(value)
#  define DM_NATIVE_TO_LE64(value) DM_SWAP_64_LE_BE(value)
#  define DM_BE64_TO_NATIVE(value) ((Uint64) (value))
#  define DM_NATIVE_TO_BE64(value) ((Uint64) (value))

#elif (SDL_BYTEORDER == SDL_LIL_ENDIAN)

#  define DM_LE16_TO_NATIVE(value) ((Uint16) (value))
#  define DM_LE32_TO_NATIVE(value) ((Uint32) (value))
#  define DM_NATIVE_TO_LE16(value) ((Uint16) (value))
#  define DM_NATIVE_TO_LE32(value) ((Uint32) (value))

#  define DM_BE16_TO_NATIVE(value) DM_SWAP_16_LE_BE(value)
#  define DM_BE32_TO_NATIVE(value) DM_SWAP_32_LE_BE(value)
#  define DM_NATIVE_TO_BE16(value) DM_SWAP_16_LE_BE(value)
#  define DM_NATIVE_TO_BE32(value) DM_SWAP_32_LE_BE(value)

#  define DM_LE64_TO_NATIVE(value) ((Uint64) (value))
#  define DM_NATIVE_TO_LE64(value) ((Uint64) (value))
#  define DM_BE64_TO_NATIVE(value) DM_SWAP_64_LE_BE(value)
#  define DM_NATIVE_TO_BE64(value) DM_SWAP_64_LE_BE(value)
#endif


#ifdef __cplusplus
}
#endif

#endif // DMLIB_H