view dmlib.h @ 510:43ea59887c69

Start work on making C64 formats encoding possible by changing DMDecodeOps to DMEncDecOps and adding fields and op enums for custom encode functions, renaming, etc. Split generic op sanity checking into a separate function in preparation for its use in generic encoding function.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 19 Nov 2012 15:06:01 +0200
parents 443228332e5b
children a9f4340bce29
line wrap: on
line source

/*
 * DMLib
 * -- Main header file
 * Programmed and designed by Matti 'ccr' Hamalainen
 * (C) Copyright 2011-2012 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_video.h>
#include <stdarg.h>

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

#ifdef __cplusplus
extern "C" {
#endif

// Defaults
#define DM_PROG_AUTHOR      "By Matti 'ccr' Hamalainen (C) Copyright 2012 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_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_INTERNAL,

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


// 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 type
 */
typedef union
{
    Sint64 dw;
    Sint32 w[2];
} DMFixedPoint;


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


/* Macros for fixed point math
 */
#if __GNUC__ >= 3
#  define FP_SET(a, k) a.dw = k ## ULL
#else
#  define FP_SET(a, k) a.dw = k
#endif

#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_GETH(a) a.w[0]
#  define FP_GETL(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_GETH(a) a.w[1]
#  define FP_GETL(a) a.w[0]
#else
#  error Unsupported byte order!
#endif

#define FP_PRINTF(a)   printf("%.8x:%.8x", FP_GETH(a), FP_GETL(a))
#define FP_PRINTF32(a) printf("%.4x:%.4x", FP_GETH(a), FP_GETL(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
} DMRGBA32;


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));
}


/* Generic parameter interpolation
 */
#define DMM_S_CURVE(t)     ((t) * (t) * (3.0f - 2.0f * (t)))
#define DMM_LERP(t, a, b)  ((a) + (t) * ((b) - (a)))

typedef struct
{
    DMFloat start, end, nsteps;
} DMLerpContext;


void       dmLerpInit(DMLerpContext *ctx, DMFloat start, DMFloat end, DMFloat nsteps);
DMFloat    dmCatmullRom(const DMFloat t, const DMFloat p0, const DMFloat p1, const DMFloat p2, const DMFloat p3);


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));
}


static inline DMFloat dmLerpSCurve(DMLerpContext *ctx, const DMFloat step)
{
    const DMFloat n = step / ctx->nsteps;
    const DMFloat v = DMM_S_CURVE(n);
    return DMM_LERP(v, ctx->start, ctx->end);
}


static inline DMFloat dmLerpSCurveClamp(DMLerpContext *ctx, const DMFloat step)
{
    const DMFloat n = dmClamp10(step / ctx->nsteps);
    const DMFloat v = DMM_S_CURVE(n);
    return DMM_LERP(v, ctx->start, ctx->end);
}


static inline DMFloat dmLerp1(DMLerpContext *ctx, const DMFloat step)
{
    const DMFloat v = step / ctx->nsteps;
    return DMM_LERP(v, ctx->start, ctx->end);
}


static inline DMFloat dmLerp1Clamp(DMLerpContext *ctx, const DMFloat step)
{
    const DMFloat v = dmClamp10(step / ctx->nsteps);
    return DMM_LERP(v, ctx->start, ctx->end);
}


static inline DMFloat dmCatmullRomClamp(const DMFloat t, const DMFloat p0, const DMFloat p1, const DMFloat p2, const DMFloat p3)
{
    return dmCatmullRom(dmClamp10(t), p0, p1, p2, p3);
}


/* Perlin noise
 */
void       dmPerlinInit(void);
DMFloat    dmPerlinNoise2D(DMFloat x, DMFloat y, DMFloat alpha, DMFloat beta, int n);


/* 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);

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


/* Misc functions
 */
#ifdef DM_GFX_MISC
void       dmFillRect(SDL_Surface *screen, int x0, int y0, int x1, int y1, const Uint32 col);
void       dmDrawHLine(SDL_Surface *screen, int x0, int x1, int yc, const Uint32 col);
void       dmDrawVLine(SDL_Surface *screen, int y0, int y1, int xc, const Uint32 col);

void       dmDrawBox3D(SDL_Surface *screen, int x0, int y0, int x1, int y1, Uint32 ucol, Uint32 dcol);
void       dmFillBox3D(SDL_Surface *screen, int x0, int y0, int x1, int y1, Uint32 bgcol, Uint32 ucol, Uint32 dcol);


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);
}
#endif


/* 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, ...);
void       dmErrorVA(const char *fmt, va_list);
void       dmError(const char *fmt, ...);

void *     dmMalloc(size_t);
void *     dmMalloc0(size_t);
void *     dmRealloc(void *, size_t);
void *     dmCalloc(size_t, size_t);
void       dmFree(void *);

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

int         dmGetErrno();
const char *dmErrorStr(int error);

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


/* 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)))

#ifdef DM_HAVE_64BIT
#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)))
#endif

/* 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))

#    ifdef DM_HAVE_64BIT
#        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))
#    endif

#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)

#    ifdef DM_HAVE_64BIT
#        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
#endif


#ifdef __cplusplus
}
#endif

#endif // DMLIB_H