#include <stdint.h>

#ifndef DRV_H_SENTINEL
#define DRV_H_SENTINEL

/* convenience pseudo-functions */
#define drv_event_gettype(x) (x & 0xF000)
#define drv_event_getval(x) (x & 0x0FFF)


/* define categories of input events */
enum DRV_INPUT_TYPE {
  DRV_INPUT_NONE      = 0x0000,
  DRV_INPUT_KEYDOWN   = 0x1000,
  DRV_INPUT_KEYUP     = 0x2000,
  DRV_INPUT_JOYDOWN   = 0x3000,
  DRV_INPUT_JOYUP     = 0x4000,
  DRV_INPUT_JOYAXDOWN = 0x5000,
  DRV_INPUT_JOYAXUP   = 0x6000,
  DRV_INPUT_QUIT      = 0x7000
};

/* define input events / joypad keys are always 0x1XX, keyb keys 0x2XX */
enum DRV_INPUT_KEY {
  /* joypad keys */
  DRV_INPUT_JOY_1 = 0x101,
  DRV_INPUT_JOY_2 = 0x102,
  DRV_INPUT_JOY_3 = 0x103,
  DRV_INPUT_JOY_4 = 0x104,
  DRV_INPUT_JOY_5 = 0x105,
  DRV_INPUT_JOY_6 = 0x106,
  DRV_INPUT_JOY_7 = 0x107,
  DRV_INPUT_JOY_8 = 0x108,
  DRV_INPUT_JOY_9 = 0x109,
  DRV_INPUT_JOY_10 = 0x10A,
  DRV_INPUT_JOY_11 = 0x10B,
  DRV_INPUT_JOY_12 = 0x10C,
  DRV_INPUT_JOY_13 = 0x10D,
  DRV_INPUT_JOY_14 = 0x10E,
  DRV_INPUT_JOY_15 = 0x10F,
  DRV_INPUT_JOY_16 = 0x110,
  DRV_INPUT_JOYAX_1POS = 0x111,
  DRV_INPUT_JOYAX_1NEG = 0x112,
  DRV_INPUT_JOYAX_2POS = 0x113,
  DRV_INPUT_JOYAX_2NEG = 0x114,
  DRV_INPUT_JOYAX_3POS = 0x115,
  DRV_INPUT_JOYAX_3NEG = 0x116,
  DRV_INPUT_JOYAX_4POS = 0x117,
  DRV_INPUT_JOYAX_4NEG = 0x118,
  /* keyboard keys */
  DRV_INPUT_KEY_ESC = 0x201,
  DRV_INPUT_KEY_RET = 0x202,
  DRV_INPUT_KEY_TAB = 0x203,
  DRV_INPUT_KEY_SPC = 0x204,
  DRV_INPUT_KEY_BKSPC = 0x205,
  DRV_INPUT_KEY_LCTRL = 0x206,
  DRV_INPUT_KEY_RCTRL = 0x207,
  DRV_INPUT_KEY_LSHIFT = 0x208,
  DRV_INPUT_KEY_RSHIFT = 0x209,
  DRV_INPUT_KEY_LALT = 0x20A,
  DRV_INPUT_KEY_RALT = 0x20B,
  DRV_INPUT_KEY_F1 = 0x20C,
  DRV_INPUT_KEY_F2 = 0x20D,
  DRV_INPUT_KEY_F3 = 0x20E,
  DRV_INPUT_KEY_F4 = 0x20F,
  DRV_INPUT_KEY_F5 = 0x210,
  DRV_INPUT_KEY_F6 = 0x211,
  DRV_INPUT_KEY_F7 = 0x212,
  DRV_INPUT_KEY_F8 = 0x213,
  DRV_INPUT_KEY_F9 = 0x214,
  DRV_INPUT_KEY_F10 = 0x215,
  DRV_INPUT_KEY_F11 = 0x216,
  DRV_INPUT_KEY_F12 = 0x217,
  DRV_INPUT_KEY_UP = 0x218,
  DRV_INPUT_KEY_DOWN = 0x219,
  DRV_INPUT_KEY_LEFT = 0x21A,
  DRV_INPUT_KEY_RIGHT = 0x21B,
  DRV_INPUT_KEY_PGUP = 0x21C,
  DRV_INPUT_KEY_PGDOWN = 0x21D,
  DRV_INPUT_KEY_HOME = 0x21E,
  DRV_INPUT_KEY_END = 0x21F,
  DRV_INPUT_KEY_INS = 0x220,
  DRV_INPUT_KEY_DEL = 0x221,
  DRV_INPUT_KEY_LWIN = 0x222,
  DRV_INPUT_KEY_RWIN = 0x223,
  DRV_INPUT_KEY_MENU = 0x224,
  DRV_INPUT_KEY_0 = 0x225,
  DRV_INPUT_KEY_1 = 0x226,
  DRV_INPUT_KEY_2 = 0x227,
  DRV_INPUT_KEY_3 = 0x228,
  DRV_INPUT_KEY_4 = 0x229,
  DRV_INPUT_KEY_5 = 0x22A,
  DRV_INPUT_KEY_6 = 0x22B,
  DRV_INPUT_KEY_7 = 0x22C,
  DRV_INPUT_KEY_8 = 0x22D,
  DRV_INPUT_KEY_9 = 0x22E,
  DRV_INPUT_KEY_A = 0x22F,
  DRV_INPUT_KEY_B = 0x230,
  DRV_INPUT_KEY_C = 0x231,
  DRV_INPUT_KEY_D = 0x232,
  DRV_INPUT_KEY_E = 0x233,
  DRV_INPUT_KEY_F = 0x234,
  DRV_INPUT_KEY_G = 0x235,
  DRV_INPUT_KEY_H = 0x236,
  DRV_INPUT_KEY_I = 0x237,
  DRV_INPUT_KEY_J = 0x238,
  DRV_INPUT_KEY_K = 0x239,
  DRV_INPUT_KEY_L = 0x23A,
  DRV_INPUT_KEY_M = 0x23B,
  DRV_INPUT_KEY_N = 0x23C,
  DRV_INPUT_KEY_O = 0x23D,
  DRV_INPUT_KEY_P = 0x23E,
  DRV_INPUT_KEY_Q = 0x23F,
  DRV_INPUT_KEY_R = 0x240,
  DRV_INPUT_KEY_S = 0x241,
  DRV_INPUT_KEY_T = 0x242,
  DRV_INPUT_KEY_U = 0x243,
  DRV_INPUT_KEY_V = 0x244,
  DRV_INPUT_KEY_W = 0x245,
  DRV_INPUT_KEY_X = 0x246,
  DRV_INPUT_KEY_Y = 0x247,
  DRV_INPUT_KEY_Z = 0x248
};

#ifdef DRV_NOEMBED

/* initialization of the I/O subsystem. This is called by zBoy once, when the
 * emulator starts. screenwidth and screenheight must contain the size of
 * requested virtual screen, joyid is either the id of the joystick that have
 * to be polled (0..x) or -1 if no joystick support is required. */
int drv_init(int screenwidth, int screenheight, int joyid, int sound);

/* sets the window's title to a custom string */
void drv_setwintitle(char *title);

/* returns the next input event in queue */
int drv_keypoll(void);

/* loads a palette of colors into zBoy. *palette must be an array of at least
 * 256 color values written in 32bits each as RGB triplets */
int drv_loadpal(uint32_t *palette);

/* returns a monotonously increasing counter that increases by 1 every
 * milisecond */
unsigned long drv_getticks(void);

/* waits for ms miliseconds */
void drv_delay(int ms);

/* draws a pixel of 'color' color at location [x,y] in zBoy's memory buffer.
 * color is an index of the palette. the position [0,0] is located at the
 * upper left corner of the virtual screen */
void drv_putpixel(int x, int y, int color);

/* renders the screen from the memory buffer into the actual screen */
void drv_refreshscreen(void);

/* unpause the sound system (make sure to enqueue some sound data before) */
void drv_soundunpause(void);

/* enqueue sound data (samples are 8-bit, unsigned, stereo (LR) @ 44100 hz) */
void drv_soundqueue(void *sbuff, unsigned short bytelen);

/* returns the amount of sound bytes that are awaiting to be played */
unsigned short drv_soundgetqueuelen(void);

/* deinitialize the I/O subsystem. this is called just before zBoy quits */
int drv_close(void);

/* provides a directory for storing user files, guaranteed to be writeable.
 * *dir must point to a valid area that will be filled with a null-terminated
 * string containing the save directory. maxlen is the number of bytes
 * available in *dir */
void drv_getsavedir(char *dir, int maxlen);

#endif
#endif