#ifndef	GENERIC_H
#define	GENERIC_H
#include "rawkeys.h"
#include "rawmouse.h"

#if defined(BROKEN_SPRINTF) && defined(HAVE_SNPRINTF)
# undef	 sprintf
# define sprintf(str, format, args...) snprintf(str, 256, format, ##args)
#endif								/* BROKEN_SPRINTF */

#ifdef	__GNUC__
# define __packed __attribute__ ((packed))
#else
# define __packed
#endif

#ifdef	PROFILE
# undef  inline
# define inline							/* no inlining while profiling */
# undef  static							/* no statics while profiling */
# define static
# define NOASM							/* profile implies NOASM */
#endif

#ifdef	__STRICT_ANSI__
# undef  inline
# define inline							/* no inlining in ANSI-C */
#endif

#define	HANDLE	int
#include "generic-debug.h"

#ifdef	NOASM
# undef  __asm__
# define __asm__						/* no asm-statements while compiling */
# define staticvar
#else
# define staticvar static
#endif

#undef	FALSE
#undef	TRUE
typedef enum {
  FALSE =  0,							/* nothing */
  TRUE  = ~0							/* everything */
} __packed bool;

struct rgb {							/* red/green/blue */
  unsigned char r, g, b;
} __packed;

struct argb {							/* alpha/red/green/blue */
  unsigned char a;
  struct rgb rgb;
} __packed;

struct DisplayDimension {
  bool changedOffset;						/* offset of display-device in global desktop (eg. the window on a screen) */
  short int X, Y;
  bool changedSize;						/* size of display-device in global desktop (eg. the window on a screen) */
  short int Width, Height;
  bool changedDesktopOffset;					/* offset of global desktop (eg. the screen) */
  short int dtX, dtY;
  bool changedDesktopSize;					/* size of global desktop (eg. the screen) */
  short int dtWidth, dtHeight;

  bool changedBuffer;						/* the actual used framebuffer */
  void *frameBuffer;						/* address of the buffer to use for offscreen-rendering */
#ifdef	USE_ZBUFFER
  unsigned short int *zBuffer;					/* address for zbuffer-comparisons */
#endif
  char frameDepth;						/* the depth in bits */
  char frameBPP;						/* the depth in BitPerPel */
  int frameSize;						/* maximum size allowed to use */

  short int ID;							/* id-field of display */
  struct DisplayDimension *nextDim;				/* maybe we need more displays than one */
  void *driverPrivate;						/* some datas we need nothing know about; */
};

extern struct DisplayDimension localDim;

/*
 * here are the structs, externals and functions descripted,
 * that could but must not be implemented by the system-drivers
 * the file generic will ever compiled, you can activate
 * your functions with defines
 */

#undef	OPENDISPLAY
struct DisplayDimension *OpenDisplay(short int width, short int height, char depth, struct rgb *Palette);

#undef	SWAPDISPLAY
void *SwapDisplay(void *oldBuffer);

/*
 * x,y are the offsets in the display-buffer
 * width, height are the sizes of the buffer to be displayed
 * (o offsets in the buffer to be displayed, must be width*height sized)
 */
#undef	UPDATEDISPLAY
void *UpdateDisplay(void *oldBuffer, short int x, short int y, short int width, short int height);

#undef	CHANGEDISPLAY
struct DisplayDimension *ChangeDisplay(short int width, short int height, char depth, struct rgb *Palette, char *Title);

#undef	CLOSEDISPLAY
void CloseDisplay(void);

#undef	OPENKEYS
void OpenKeys(void);

#undef	GETKEYS
bool GetKeys(struct keyEvent *eventBuffer);

#undef	CLOSEKEYS
void CloseKeys(void);

#undef	OPENMOUSE
void OpenMouse(void);

#undef	GETMOUSE
void GetMouse(struct mouseEvent *eventBuffer);

#undef	CLOSEMOUSE
void CloseMouse(void);

void SetDisplay(struct DisplayDimension *dim);

/*
 * canonical system
 *
 * everything you would like to replace you must replace
 * in the include-files for your system, that could be a
 * cpu-type or os-type
 */
#include "@target_cpu@/@target_cpu@.h"
#include "@target_cpu@/@target_os@/@target_os@.h"

/*
 * if you like you can specify a global register to pass the base
 * in, then it is like indirect variable-access via the framepointer
 */
#ifndef	__memBase
#define	__memBase	register struct memory *bspMem
#endif

/*
 * some system aspecially little-endian systems requires some
 * special kind of file-attributes, textfiles could be opened
 * as standard, binary file must have the binary-attribute
 * upto now i dont know if the low-level-io functions support
 * that behaviour
 */
#ifndef	READ_BINARY
# if (WORDS_BIGENDIAN == 1)
#   define H_READ_BINARY		O_RDONLY
#   define F_READ_BINARY		"r"
# else
#   define H_READ_BINARY		O_RDONLY
#   define F_READ_BINARY		"rb"
# endif
#endif
#ifndef	WRITE_BINARY
# if (WORDS_BIGENDIAN == 1)
#  define H_WRITE_BINARY		(O_WRONLY | O_CREAT | O_TRUNC)
#  define F_WRITE_BINARY		"w"
# else
#  define H_WRITE_BINARY		(O_WRONLY | O_CREAT | O_TRUNC)
#  define F_WRITE_BINARY		"wb"
# endif
#endif
#ifndef	READWRITE_BINARY_OLD
# if (WORDS_BIGENDIAN == 1)
#  define H_READWRITE_BINARY_OLD	(O_RDWR | O_CREAT)
#  define F_READWRITE_BINARY_OLD	"r+"
# else
#  define H_READWRITE_BINARY_OLD	(O_RDWR | O_CREAT)
#  define F_READWRITE_BINARY_OLD	"rb+"
# endif
#endif
#ifndef	READWRITE_BINARY_NEW
# if (WORDS_BIGENDIAN == 1)
#  define H_READWRITE_BINARY_NEW	(O_RDWR | O_CREAT | O_TRUNC)
#  define F_READWRITE_BINARY_NEW	"w+"
# else
#  define H_READWRITE_BINARY_NEW	(O_RDWR | O_CREAT | O_TRUNC)
#  define F_READWRITE_BINARY_NEW	"wb+"
# endif
#endif

#ifndef	MATCH
unsigned char Match(register struct rgb *rawpix, register struct rgb *Palette);
#endif

/*
 * at the moment the special compressor isnt available for other systems
 * than m68k, take a look at the LZWSfiles in this directory for the
 * growing c-version, maybe you could help
 */
#ifndef	LZWS
#define	LZWSCrunch(a, b, c, d, e) (0)
#define	LZWSDecrunch(a, b, c) (0)
#define	LZWSSize(a) (0)
#define	ERROR 0
#endif

#ifndef	OPENDISPLAY						/* our offscreen-renderer supports all display-modes */
#define	DRIVER_8BIT
#define	DRIVER_16BIT
#define	DRIVER_24BIT
#define	DRIVER_32BIT
#define	DRIVER_DEFAULT	8
#endif

/*
 * if you have choosen an unsupported defaultdriver
 * you getll get a error here
 */
#if !defined(DRIVER_8BIT) && (DRIVER_DEFAULT == 8)
#error	"unsupported default driver choosen"
#endif
#if !defined(DRIVER_16BIT) && (DRIVER_DEFAULT == 16)
#error	"unsupported default driver choosen"
#endif
#if !defined(DRIVER_24BIT) && (DRIVER_DEFAULT == 24)
#error	"unsupported default driver choosen"
#endif
#if !defined(DRIVER_32BIT) && (DRIVER_DEFAULT == 32)
#error	"unsupported default driver choosen"
#endif

#ifdef INLINE_BIGENDIAN
#ifndef	SWAPSHORT
#define	SWAPSHORT
static short SwapShort(short l);
static inline short SwapShort(short l)
{
  unsigned char b1, b2;

  b1 = l & 255;
  b2 = (l >> 8) & 255;

  return (b1 << 8) + b2;
}
#endif

#ifndef	SWAPLONG
#define	SWAPLONG
static int SwapLong(int l);
static inline int SwapLong(int l)
{
  unsigned char b1, b2, b3, b4;

  b1 = l & 255;
  b2 = (l >> 8) & 255;
  b3 = (l >> 16) & 255;
  b4 = (l >> 24) & 255;

  return ((int)b1 << 24) + ((int)b2 << 16) + ((int)b3 << 8) + b4;
}

#endif

#ifndef	SWAPFLOAT
#define	SWAPFLOAT
static float SwapFloat(float l);
static inline float SwapFloat(float l)
{
  union {
    unsigned char b[4];
    float f;
  } in, out;

  in.f = l;
  out.b[0] = in.b[3];
  out.b[1] = in.b[2];
  out.b[2] = in.b[1];
  out.b[3] = in.b[0];

  return out.f;
}
#endif
#endif

#if (WORDS_BIGENDIAN == 1)
#define BigShort(a) (a)
#define LittleShort(a) SwapShort(a)
#define BigLong(a) (a)
#define LittleLong(a) SwapLong(a)
#define BigFloat(a) (a)
#define LittleFloat(a) SwapFloat(a)
#else
#define BigShort(a) SwapShort(a)
#define LittleShort(a) (a)
#define BigLong(a) SwapLong(a)
#define LittleLong(a) (a)
#define BigFloat(a) SwapFoat(a)
#define LittleFloat(a) (a)
#endif

#endif
