[from now] 2012/09/25 22:29:04

diff --git a/OMakefile b/OMakefile
index ac0dcea..4866eea 100644
--- a/OMakefile
+++ b/OMakefile
@@ -18,6 +18,7 @@
 # The standard OMakefile.
 # You will usually need to modify this file for your project.
 open MyOCaml
+open common/Function

 ########################################################################
 # Phony targets are scoped, so you probably want to declare them first.
@@ -99,7 +100,11 @@ OCAMLOPTFLAGS +=
 #
 LIBRARY_NAME = sdlcaml
 #
+REQUIRE[] =
+	src/sdl_initflags.h
+	src/sdl_generic.h

+RequiredFiles($(REQUIRE))
 .DEFAULT: src/sdlcaml$(EXT_LIB)

 .PHONY: test
diff --git a/config/OMakefile b/config/OMakefile
index 4d10787..421e7ae 100644
--- a/config/OMakefile
+++ b/config/OMakefile
@@ -77,6 +77,12 @@ OCAMLFLAGS    += -Wa -annot

 INCLUDES += /usr/include/caml

+sdl_generic.h: generic$(EXE) sdl_generic.h.in
+	section
+		rep = $(concat \\n, $(shella $<))
+		sed -e "s/#FLAGS/$(rep)/" $(nth 1, $+) > $@
+		cp $@ ../src/$@
+
 sdl_initflags.h: initflag$(EXE) sdl_initflags.h.in
 	section
 		initflags = $(concat \\n, $(shella $<))
@@ -88,6 +94,11 @@ initflag$(EXE): outputflag.c initflag.ml
 	$(OCAMLMKLIB) -o $(removesuffix $@) $(addsuffix $(EXT_OBJ), $(removesuffix $<))
 	$(OCAMLOPT) -o $@ $(nth 1, $+) -cclib "$(absname lib$(removesuffix $@)$(EXT_LIB))"

+generic$(EXE): outputflag.c generic.ml
+	$(OCAMLC) -ccopt "$(PREFIXED_INCLUDES)" -o $(addsuffix $(EXT_OBJ), $(removesuffix $<)) -c $<
+	$(OCAMLMKLIB) -o $(removesuffix $@) $(addsuffix $(EXT_OBJ), $(removesuffix $<))
+	$(OCAMLOPT) -o $@ $(nth 1, $+) -cclib "$(absname lib$(removesuffix $@)$(EXT_LIB))"
+
 #
 # OCAML_LIBS += ../lib/mylib
 # OCAML_CLIBS +=
@@ -95,7 +106,7 @@ initflag$(EXE): outputflag.c initflag.ml
 # OCAML_LIB_FLAGS +=
 # OCAML_PACKAGE_NAME =
 #
-.DEFAULT: sdl_initflags.h
+.DEFAULT: sdl_initflags.h sdl_generic.h

 .PHONY: clean

@@ -105,5 +116,6 @@ clean:
 	rm -f *.a
 	rm -f *.cmi
 	rm -f *.cmx
-	rm -f sdl_initflags.h
+	rm -f *.h
 	rm -f initflag$(EXE)
+	rm -f generic$(EXE)
diff --git a/config/outputflag.c b/config/outputflag.c
index 83f5598..27ead26 100644
--- a/config/outputflag.c
+++ b/config/outputflag.c
@@ -3,3 +3,8 @@
 CAMLprim value variant_hash(value variant) {
   return Val_int(caml_hash_variant(variant));
 }
+
+/* convert variant to int  */
+CAMLprim value variant_tag(value variant) {
+  return Val_int(Int_val(variant));
+}
diff --git a/config/sdl_initflags.h b/config/sdl_initflags.h
deleted file mode 100644
index 7fd8582..0000000
--- a/config/sdl_initflags.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __SDL_INITFLAGS_H__
-#define __SDL_INITFLAGS_H__
-
-#include "common.h"
-
-#define MLTAG_TIMER (474476363)
-#define MLTAG_VIDEO (-371943241)
-#define MLTAG_AUDIO (-891461267)
-#define MLTAG_CDROM (34847711)
-#define MLTAG_JOYSTICK (-353443463)
-#define MLTAG_EVENTTHREAD (123518089)
-#define MLTAG_NOPARACHUTE (1032187521)
-#define MLTAG_EVERYTHING (566131943)
-
-extern lookup_info ml_init_flag_table[];
-
-#endif /*__SDL_INITFLAGS_H__*/
diff --git a/src/OMakefile b/src/OMakefile
index dae0117..0202d2c 100644
--- a/src/OMakefile
+++ b/src/OMakefile
@@ -88,7 +88,7 @@ OCAMLFLAGS    += -annot
 CFILES = $(removesuffix $(ls *.c))

 %$(EXT_OBJ): %.c :scanner: scan-c-%.c
-	$(OCAMLC) -ccopt "$(SDL_CONFIGURE)" -verbose -o $@ -c $<
+	$(OCamlC) -ccopt "-std=c99 $(SDL_CONFIGURE)" -verbose -o $@ -c $<

 FILES = $(removesuffix $(ls *.ml))

@@ -104,7 +104,9 @@ OCAML_LIB_FLAGS += -cclib "$(addprefix $(absname $(CWD))/, $(STATICLIBS))"
 OCAML_LIB_FLAGS += -verbose
 # OCAML_PACKAGE_NAME =
 #
-RequiredFiles(../config/sdl_initflags.h)
+REQUIRE[] =
+	sdl_initflags.h
+	sdl_generic.h

 MyOCamlPackage($(LIBRARY_NAME), $(FILES), $(CFILES), $(EMPTY))

diff --git a/src/common.c b/src/common.c
index b705450..554386b 100644
--- a/src/common.c
+++ b/src/common.c
@@ -1,4 +1,6 @@
 #include <caml/mlvalues.h>
+#include <caml/memory.h>
+#include <caml/alloc.h>
 #include "common.h"

 int ml_lookup_to_c(lookup_info *table, value key) {
@@ -35,9 +37,17 @@ value ml_lookup_from_c(lookup_info *table, int value) {
   return Val_int(0);
 }

+int ml_table_size(lookup_info* table) {
+  if (table == NULL) {
+    return 0;
+  }
+
+  return table[0].value;
+}
+
 /*****************************************************/

-CAMLprim value head(value list) {
+value head(value list) {

   if (list != Val_emptylist) {
     return Field(list, 0);
@@ -46,7 +56,7 @@ CAMLprim value head(value list) {
   }
 }

-CAMLprim value tail(value list) {
+value tail(value list) {

   if (list != Val_emptylist) {
     return Field(list, 1);
@@ -55,6 +65,16 @@ CAMLprim value tail(value list) {
   }
 }

+/* add cons to head of list */
+value add_head(value list, value data) {
+  CAMLparam2(list, data);
+  CAMLlocal1(cons);
+  cons = caml_alloc(2,0);
+  Store_field(cons, 0, data);
+  Store_field(cons, 1, list);
+  CAMLreturn(cons);
+}
+
 int is_not_nil(value list) {
   return (list != Val_emptylist);
 }
diff --git a/src/common.h b/src/common.h
index 9119156..40ca688 100644
--- a/src/common.h
+++ b/src/common.h
@@ -3,6 +3,8 @@

 #include <caml/mlvalues.h>

+#define Val_none (Val_int(0))
+
 typedef struct lookup_info {
   value key;
   int value;
@@ -15,10 +17,12 @@ typedef struct lookup_info {
  */
 int ml_lookup_to_c(lookup_info *table, value key);
 value ml_lookup_from_c(lookup_info *table, int value);
+int ml_table_size(lookup_info *table);

 /** list operation helper used from C */
 value head(value list);
 value tail(value list);
+value add_head(value list, value cons);
 int is_not_nil(value list);

 /** operations for 'a option */
diff --git a/src/sdl_event.ml b/src/sdl_event.ml
index 09d4dea..1ae530c 100644
--- a/src/sdl_event.ml
+++ b/src/sdl_event.ml
@@ -18,7 +18,7 @@ type event_state =
 type app_state =
 | APPMOUSEFOCUS                         (** has mouse focus *)
 | APPINPUTFORCUS                        (** has keyboard focus *)
-| APPASCTIVE                            (** application is visible *)
+| APPACTIVE                            (** application is visible *)

 (** The application active event structure  *)
 type active_event = {
@@ -28,7 +28,7 @@ type active_event = {

 (** This Event Structure use both events whether SDL_KEYDOWN and SDL_KEYUP. *)
 type keyboard_event = {
-  keysym: Sdl_key.keysym        (** key that is occured event  *)
+  keysym: Sdl_key.key_info           (** key that is occured event  *)
 }

 (** Mouse motion event structure  *)
@@ -45,11 +45,18 @@ type mouse_button_event = {
   index:int;    (** the mouse button index *)
 }

-(** Joystick axis motion event strucutre  *)
+(**
+ * Joystick axis motion event strucutre.
+ *
+ * Usually, On most modern joysticks the X axis
+ * is represented by axis 0, and the Y axis by axis 1.
+ * If your joysticks has difference axis index, you have to
+ * detect to need axis index before.
+ *)
 type joy_axis_event = {
   index:int;                             (** joystick device index  *)
-  axis:Sdl_input.joy_axis;               (** joystick axis index *)
-  value:int;                                  (** axis value  *)
+  axis:int;                              (** joystick axis index *)
+  value:int;                             (** axis value  *)
 }

 (** Joystick trackball motion event structure  *)
@@ -105,11 +112,11 @@ type event_type =
 | SDL_JOYHATMOTION                      (** related SDL_JoyHatEvent *)
 | SDL_JOYBUTTONDOWN                     (** related SDL_JoyButtonEvent *)
 | SDL_JOYBUTTONUP                       (** related SDL_JoyButtonEvent *)
-| SDL_QUIT                              (** related SDL_QuitEvent *)
-| SDL_SYSWMEVENT                        (** related SDL_SysWMEvent *)
 | SDL_VIDEORESIZE                       (** related SDL_ResizeEvent *)
 | SDL_VIDEOEXPOSE                       (** related SDL_ExposeEvent *)
+| SDL_QUIT                              (** related SDL_QuitEvent *)
 | SDL_USEREVENT                         (** related SDL_UserEvent *)
+| SDL_SYSWMEVENT                        (** related SDL_SysWMEvent *)

 (**
  * Inplementation for C structure of {b SDL_Event}.
diff --git a/src/sdl_input.ml b/src/sdl_input.ml
index 014e044..aeba2bd 100644
--- a/src/sdl_input.ml
+++ b/src/sdl_input.ml
@@ -24,18 +24,6 @@ type mouse_state = {
   state:mouse_button_state list  (** see {!mouse_button_state} *)
 }

-(**
- * type of Joystick axis. Usually, On most modern joysticks the X axis
- * is represented by axis 0, and the Y axis by axis 1.
- * JOY_XAXIS is mapped to X axis, and JOY_YAXIS is to Y axis.
- * If any joysticks that X and Y axis is not 0 and 1 need to use,
- * you can substitute JOY_ANY_AXIS for them.
- *)
-type joy_axis =
-| JOY_XAXIS
-| JOY_YAXIS
-| JOY_ANY_AXIS of int
-
 (** Variant for hat values *)
 type hat_state =
 | HAT_CENTERED
@@ -72,7 +60,7 @@ external get_key_state: ?num:int -> unit -> Sdl_key.state_map
  * @param unit dummy argument
  * @return list of the state of modify keys.
  *)
-external get_mod_state: unit -> Sdl_key.mod_key list = "sdlcaml_get_mod_state"
+external get_mod_state: unit -> Sdl_key.modify_key list = "sdlcaml_get_mod_state"

 (**
  * Enable of disable keyboard repeat rate.
diff --git a/src/sdl_key.ml b/src/sdl_key.ml
index 52d9dcf..9666895 100644
--- a/src/sdl_key.ml
+++ b/src/sdl_key.ml
@@ -1,7 +1,9 @@
+
+
 (**
- * Mapping {b SDL_keysym}. These often uses with {!Sdl_KeyStateMap.state_map}
+ * Mapping {b SDLkey}. These often uses with {!Sdl_KeyStateMap.state_map}
  *)
-type keysym =
+type key_synonym =
 | SDLK_BACKSPACE                        (** backspace *)
 | SDLK_TAB                              (** tab *)
 | SDLK_CLEAR                            (** clear *)
@@ -140,7 +142,7 @@ type keysym =
  * Mapping modify keys in {b SDL_keysym}.
  * These often uses with {!Sdl_event.get_mod_state}
  *)
-type mod_key =
+type modify_key =
 | KMOD_NONE                             (** No modifiers applicable *)
 | KMOD_NUM                              (** Numlock is down *)
 | KMOD_CAPS                             (** Capslock is down *)
@@ -154,10 +156,20 @@ type mod_key =
 | KMOD_SHIFT                            (** A Shift key is down *)
 | KMOD_ALT                              (** An Alt key is down *)

+(**
+   Mapping {b SDL_keysym}. however, {!keysym.mod_key} is the list of
+   current modify key state. If some {!mod_key} variants are
+   contained, it means that they are pressed now.
+*)
+type key_info = {
+  synonym:key_synonym;
+  modify_state:modify_key list;
+}
+
 (** Map for key and key state. *)
 module StateMap = Map.Make (
   struct
-    type t = keysym
+    type t = key_synonym
     let compare x y =
       if x < y then -1
       else if x = y then 0
diff --git a/src/sdl_stub.c b/src/sdl_stub.c
index 200fbb5..525ec93 100644
--- a/src/sdl_stub.c
+++ b/src/sdl_stub.c
@@ -29,6 +29,7 @@ static void sdlcaml_inner_quit(void) {
 }

 CAMLprim value sdlcaml_init(value auto_clean, value flags) {
+  CAMLparam2(auto_clean, flags);
   int init_flag = ml_make_init_flag(flags);

   if (SDL_Init(init_flag) < 0) {
@@ -40,17 +41,21 @@ CAMLprim value sdlcaml_init(value auto_clean, value flags) {
     atexit(sdlcaml_inner_quit);
   }

-  return Val_unit;
+  CAMLreturn(Val_unit);
 }

 CAMLprim value sdlcaml_quit(value unit) {
   /* only calling inner function */
+  CAMLparam0();
   sdlcaml_inner_quit();
+  CAMLnoreturn;
   return Val_unit;
 }

 CAMLprim value sdlcaml_version(value unit) {
-  value tuple = caml_alloc(3, 0);
+  CAMLparam0();
+  CAMLlocal1(tuple);
+  tuple = caml_alloc(3, 0);

   SDL_version version;
   SDL_VERSION(&version);
@@ -60,22 +65,25 @@ CAMLprim value sdlcaml_version(value unit) {
   Store_field( tuple, 1, Val_int(version.minor));
   Store_field( tuple, 2, Val_int(version.patch));

-  return ( tuple );
+  CAMLreturn(tuple);
 }

 CAMLprim value sdlcaml_init_subsystem(value flag) {
+  CAMLparam1(flag);
   int c_flag = ml_lookup_to_c(ml_init_flag_table, flag);

   if (SDL_InitSubSystem(c_flag)) {
     caml_raise_with_string(caml_named_value("SDL_init_exception"),
                            SDL_GetError());
   }
-  return Val_unit;
+
+  CAMLreturn(Val_unit);
 }

 CAMLprim value sdlcaml_quit_subsystem(value flag) {
+  CAMLparam1(flag);
   int c_flag = ml_lookup_to_c(ml_init_flag_table, flag);

   SDL_QuitSubSystem(c_flag);
-  return Val_unit;
+  CAMLreturn(Val_unit);
 }
[from now] 2012/09/25 22:29:43

diff --git a/config/generic.ml b/config/generic.ml
new file mode 100644
index 0000000..7134c06
--- /dev/null
+++ b/config/generic.ml
@@ -0,0 +1,13 @@
+let variants = [
+  "PRESSED";
+  "RELEASED";
+]
+
+external variant_hash : string -> int = "variant_hash"
+
+let _ =
+  let print_hash variant_name =
+    let hash = variant_hash variant_name in
+    Printf.printf "#define MLTAG_%s (%d)\n" variant_name hash
+  in
+  List.iter print_hash variants
diff --git a/config/sdl_generic.h.in b/config/sdl_generic.h.in
new file mode 100644
index 0000000..91c33ec
--- /dev/null
+++ b/config/sdl_generic.h.in
@@ -0,0 +1,10 @@
+#ifndef __SDL_GENERIC_H__
+#define __SDL_GENERIC_H__
+
+#include "common.h"
+
+#FLAGS
+
+extern lookup_info ml_generic_button_table[];
+
+#endif /*__SDL_GENERIC_H__*/
diff --git a/src/sdl_event_stub.c b/src/sdl_event_stub.c
new file mode 100644
index 0000000..d8b188d
--- /dev/null
+++ b/src/sdl_event_stub.c
@@ -0,0 +1,371 @@
+#include <SDL.h>
+
+#include <caml/mlvalues.h>
+#include <caml/memory.h>
+#include <caml/alloc.h>
+#include <caml/fail.h>
+#include "common.h"
+#include "sdl_generic.h"
+#include "sdl_key_trans.h"
+#include "sdl_input_trans.h"
+
+enum EVENTTAG {
+  ETAG_ACTIVE      = 0,
+  ETAG_KEYDOWN     = 1,
+  ETAG_KEYUP       = 2,
+  ETAG_MOTION      = 3,
+  ETAG_BUTTONDOWN  = 4,
+  ETAG_BUTTONUP    = 5,
+  ETAG_JAXIS       = 6,
+  ETAG_JBALL       = 7,
+  ETAG_JHAT        = 8,
+  ETAG_JBUTTONDOWN = 9,
+  ETAG_JBUTTONUP   = 10,
+  ETAG_RESIZE      = 11,
+  ETAG_EXPOSE      = 12,
+  ETAG_QUIT        = 13,
+  ETAG_USER        = 14,
+  ETAG_SYSWM       = 15
+};
+
+CAMLprim value sdlcaml_pump_events(value unit) {
+  CAMLparam0();
+
+  SDL_PumpEvents();
+
+  CAMLnoreturn;
+  return Val_unit;
+}
+
+value caml_create_active_event(SDL_Event* event) {
+  CAMLparam0();
+  CAMLlocal2(event_tag, active);
+  event_tag     = caml_alloc(1, ETAG_ACTIVE);
+  active        = caml_alloc(2, 0);
+
+  Store_field(active, 0, event->active.gain == 1 ? Val_true : Val_false);
+  switch (event->active.state) {
+    case SDL_APPMOUSEFOCUS: Store_field(active, 1, Val_int(0)); break;
+    case SDL_APPINPUTFOCUS: Store_field(active, 1, Val_int(1)); break;
+    case SDL_APPACTIVE: Store_field(active, 1, Val_int(2)); break;
+    default: caml_invalid_argument("invalid state in SDL_ACTIVEEVENT");
+  }
+
+  Store_field(event_tag, 0, active);
+  CAMLreturn(event_tag);
+}
+
+value caml_create_keyboard_event(SDL_Event* event, int tag) {
+  CAMLparam0();
+  CAMLlocal4(event_tag, keyboard, keyinfo, modkey);
+  event_tag = caml_alloc(1, tag);
+  keyboard  = caml_alloc(1, 0);
+  keyinfo   = caml_alloc(2, 0);
+  modkey    = Val_emptylist;
+
+  /* set data of keysym  */
+  Store_field(keyinfo, 0, ml_lookup_from_c(ml_symkey_trans_table,
+                                           event->key.keysym.sym));
+
+  /* get current state of the modify keys including pressed now only */
+  for (int i = ml_table_size(ml_modkey_trans_table); i > 0; --i) {
+    if (event->key.keysym.mod & ml_modkey_trans_table[i].value) {
+      modkey = add_head(modkey, Val_int(ml_modkey_trans_table[i].key));
+    }
+  }
+  Store_field(keyinfo, 1, modkey);
+
+  Store_field(keyboard, 0, keyinfo);
+  Store_field(event_tag, 0, keyboard);
+
+  CAMLreturn(event_tag);
+}
+
+value caml_create_mousemotion_event(SDL_Event* event) {
+  CAMLparam0();
+  CAMLlocal3(event_tag, motion, button);
+  event_tag     = caml_alloc(1, ETAG_MOTION);
+  motion        = caml_alloc(5, 0);
+  button        = Val_emptylist;
+
+  const int MAX_BUTTON = 32;
+  int       button_states[MAX_BUTTON];
+
+  memset(button_states, 0, sizeof(int) * MAX_BUTTON);
+
+  Store_field(motion, 0, Val_int(event->motion.x));
+  Store_field(motion, 1, Val_int(event->motion.y));
+  Store_field(motion, 2, Val_int(event->motion.xrel));
+  Store_field(motion, 3, Val_int(event->motion.yrel));
+
+  /* get mouse state of as many as possible buttons */
+  for (int i = MAX_BUTTON; i > 0; --i) {
+    CAMLlocal1(state);
+    state = caml_alloc(2, 0);
+    Store_field(state, 0, Val_int(i));
+    Store_field(state, 1, ml_lookup_from_c(ml_generic_button_table,
+                                           event->motion.state & SDL_BUTTON(i)));
+
+    button = add_head(button, state);
+  }
+  Store_field(motion, 4, button);
+
+  Store_field(event_tag, 0, motion);
+
+  CAMLreturn(event_tag);
+}
+
+value caml_create_mousebutton_event(SDL_Event* event, int tag) {
+  CAMLparam0();
+  CAMLlocal3(event_tag, statelist, button);
+  event_tag = caml_alloc(1, tag);
+  statelist = caml_alloc(3, 0);
+  button    = Val_emptylist;
+
+  const int                              MAX_BUTTON = 32;
+  int                                    button_states[MAX_BUTTON];
+  memset(button_states, 0, sizeof(int) * MAX_BUTTON);
+
+  Store_field(statelist, 0, Val_int(event->button.x));
+  Store_field(statelist, 1, Val_int(event->button.y));
+
+  /* get mouse state of as many as possible buttons */
+  for (int i = MAX_BUTTON; i > 0; --i) {
+    CAMLlocal1(state);
+    state = caml_alloc(2, 0);
+    Store_field(state, 0, Val_int(i));
+    Store_field(state, 1, ml_lookup_from_c(ml_generic_button_table,
+                                           event->button.state & SDL_BUTTON(i)));
+
+    button = add_head(button, state);
+  }
+  Store_field(statelist, 2, button);
+
+  Store_field(event_tag, 0, statelist);
+
+  CAMLreturn(event_tag);
+}
+
+value caml_create_joyaxismotion_event(SDL_Event* event) {
+  CAMLparam0();
+  CAMLlocal2(event_tag, axis);
+  event_tag  = caml_alloc(1, ETAG_JAXIS);
+  axis = caml_alloc(3, 0);
+
+  Store_field(axis, 0, Val_int(event->jaxis.which));
+  Store_field(axis, 1, Val_int(event->jaxis.axis));
+  Store_field(axis, 2, Val_int(event->jaxis.value));
+
+  Store_field(event_tag, 0, axis);
+
+  CAMLreturn(event_tag);
+}
+
+value caml_create_joyballmotion_event(SDL_Event* event) {
+  CAMLparam0();
+  CAMLlocal2(event_tag, ball);
+  event_tag = caml_alloc(1, ETAG_JBALL);
+  ball      = caml_alloc(4, 0);
+
+  Store_field(ball, 0, Val_int(event->jball.which));
+  Store_field(ball, 1, Val_int(event->jball.ball));
+  Store_field(ball, 2, Val_int(event->jball.xrel));
+  Store_field(ball, 3, Val_int(event->jball.yrel));
+
+  Store_field(event_tag, 0, ball);
+
+  CAMLreturn(event_tag);
+}
+
+value caml_create_joyhatmotion_event(SDL_Event* event) {
+  CAMLparam0();
+  CAMLlocal3(event_tag, hat, switchlist);
+  event_tag  = caml_alloc(1, ETAG_JHAT);
+  hat        = caml_alloc(3, 0);
+  switchlist = Val_emptylist;
+  int state  = event->jhat.value;
+
+  Store_field(hat, 0, Val_int(event->jhat.which));
+  Store_field(hat, 1, Val_int(event->jhat.hat));
+
+  /* check all hat position in current state, but list contains
+     only bit masking result of 1.
+   */
+  for (int i = ml_table_size(ml_joyhat_trans_table); i > 0; --i) {
+    if (state & ml_joyhat_trans_table[i].value) {
+      switchlist = add_head(switchlist, Val_int(ml_joyhat_trans_table[i].key));
+    }
+  }
+  Store_field(hat, 2, switchlist);
+
+  Store_field(event_tag, 0, hat);
+
+  CAMLreturn(event_tag);
+}
+
+value caml_create_joybutton_event(SDL_Event* event, int tag) {
+  CAMLparam0();
+  CAMLlocal2(event_tag, button);
+  event_tag = caml_alloc(1, tag);
+  button    = caml_alloc(2, 0);
+
+  Store_field(button, 0, Val_int(event->jbutton.which));
+  Store_field(button, 1, Val_int(event->jbutton.button));
+
+  Store_field(event_tag, 0, button);
+
+  CAMLreturn(event_tag);
+}
+
+value caml_create_resize_event(SDL_Event* event) {
+  CAMLparam0();
+  CAMLlocal2(event_tag, resize);
+  event_tag = caml_alloc(1, ETAG_RESIZE);
+  resize    = caml_alloc(2, 0);
+
+  Store_field(resize, 0, Val_int(event->resize.w));
+  Store_field(resize, 1, Val_int(event->resize.h));
+
+  Store_field(event_tag, 0, resize);
+
+  CAMLreturn(event_tag);
+}
+
+value caml_create_expose_event(SDL_Event* event) {
+  return Val_int(ETAG_EXPOSE);
+}
+
+value caml_create_quit_event(SDL_Event* event) {
+  return Val_int(ETAG_QUIT);
+}
+
+value caml_create_user_event(SDL_Event* event) {
+  /* TODO: I have to implement somehow */
+  return Val_int(ETAG_USER);
+}
+
+value caml_create_syswm_event(SDL_Event* event) {
+  /* TODO: I decide to implement or not. */
+  return Val_int(ETAG_SYSWM);
+}
+
+/* create and return Event Structure for OCaml */
+value caml_create_event_struct(SDL_Event *event) {
+  switch (event->type) {
+    case SDL_ACTIVEEVENT:     return caml_create_active_event(event);
+    case SDL_KEYDOWN:         return caml_create_keyboard_event(event, ETAG_KEYDOWN);
+    case SDL_KEYUP:           return caml_create_keyboard_event(event, ETAG_KEYUP);
+    case SDL_MOUSEMOTION:     return caml_create_mousemotion_event(event);
+    case SDL_MOUSEBUTTONDOWN: return caml_create_mousebutton_event(event, ETAG_BUTTONDOWN);
+    case SDL_MOUSEBUTTONUP:   return caml_create_mousebutton_event(event, ETAG_BUTTONUP);
+    case SDL_JOYAXISMOTION:   return caml_create_joyaxismotion_event(event);
+    case SDL_JOYBALLMOTION:   return caml_create_joyballmotion_event(event);
+    case SDL_JOYHATMOTION:    return caml_create_joyhatmotion_event(event);
+    case SDL_JOYBUTTONDOWN:   return caml_create_joybutton_event(event, ETAG_JBUTTONDOWN);
+    case SDL_JOYBUTTONUP:     return caml_create_joybutton_event(event, ETAG_JBUTTONUP);
+    case SDL_VIDEORESIZE:     return caml_create_resize_event(event);
+    case SDL_VIDEOEXPOSE:     return caml_create_expose_event(event);
+    case SDL_QUIT:            return caml_create_quit_event(event);
+    case SDL_USEREVENT:       return caml_create_user_event(event);
+    case SDL_SYSWMEVENT:      return caml_create_syswm_event(event);
+    default:
+      caml_invalid_argument("unrecognized event type!");
+  }
+}
+
+CAMLprim value sdlcaml_poll_event(value unit) {
+  CAMLparam0();
+
+  SDL_Event event;
+  if (SDL_PollEvent(&event)) {
+    CAMLlocal2(event_struct, option);
+    event_struct = caml_create_event_struct(&event);
+
+    option = caml_alloc(1,0);
+    Store_field(option, 0, event_struct);
+    CAMLreturn(option);
+  } else {
+    CAMLreturn(Val_int(0));
+  }
+}
+
+CAMLprim value sdlcaml_wait_event(value unit) {
+  CAMLparam0();
+
+  SDL_Event event;
+  if (SDL_WaitEvent(&event)) {
+    CAMLlocal2(event_struct, option);
+    event_struct = caml_create_event_struct(&event);
+
+    option = caml_alloc(1,0);
+    Store_field(option, 0, event_struct);
+    CAMLreturn(option);
+  } else {
+    CAMLreturn(Val_int(0));
+  }
+}
+
+CAMLprim value sdlcaml_event_state(value etype, value state) {
+  CAMLparam2(etype, state);
+  int event_state = SDL_IGNORE;
+  switch (Int_val(state)) {
+    case 0: event_state = SDL_IGNORE; break;
+    case 1: event_state = SDL_ENABLE; break;
+    case 2: event_state = SDL_QUERY; break;
+    default: caml_invalid_argument("invalid event state in sdlcaml_event_state");
+  }
+
+  int event_type = 0;
+  switch (Int_val(etype)) {
+    case  0: event_type = SDL_ACTIVEEVENT; break;
+    case  1: event_type = SDL_KEYDOWN; break;
+    case  2: event_type = SDL_KEYUP; break;
+    case  3: event_type = SDL_MOUSEMOTION; break;
+    case  4: event_type = SDL_MOUSEBUTTONDOWN; break;
+    case  5: event_type = SDL_MOUSEBUTTONUP; break;
+    case  6: event_type = SDL_JOYAXISMOTION; break;
+    case  7: event_type = SDL_JOYBALLMOTION; break;
+    case  8: event_type = SDL_JOYHATMOTION; break;
+    case  9: event_type = SDL_JOYBUTTONDOWN; break;
+    case 10: event_type = SDL_JOYBUTTONUP; break;
+    case 11: event_type = SDL_VIDEORESIZE; break;
+    case 12: event_type = SDL_VIDEOEXPOSE; break;
+    case 13: event_type = SDL_QUIT; break;
+    case 14: event_type = SDL_USEREVENT; break;
+    case 15: event_type = SDL_SYSWMEVENT; break;
+    default: caml_invalid_argument("invalid event type in sdlcaml_event_state");
+  }
+
+  /* responce only return if event_state is only SDL_QUERY */
+  int response = SDL_EventState(event_type, event_state);
+  if (event_state == SDL_QUERY) {
+    CAMLlocal1(responce_val);
+    responce_val = caml_alloc(1,0);
+    Store_field(responce_val, 0, Val_int(response));
+    CAMLreturn(responce_val);
+  } else {
+    CAMLreturn(Val_none);
+  }
+}
+
+CAMLprim value sdlcaml_get_app_state(value unit) {
+  CAMLparam0();
+  CAMLlocal1(current_state);
+  current_state = Val_emptylist;
+
+  int appstate = SDL_GetAppState();
+
+  if (appstate & SDL_APPMOUSEFOCUS) {
+    current_state = add_head(current_state, Val_int(0));
+  }
+
+  if (appstate & SDL_APPINPUTFOCUS) {
+    current_state = add_head(current_state, Val_int(1));
+  }
+
+  if (appstate & SDL_APPACTIVE) {
+    current_state = add_head(current_state, Val_int(2));
+  }
+
+  CAMLreturn(current_state);
+}
diff --git a/src/sdl_generic.h b/src/sdl_generic.h
new file mode 100644
index 0000000..01cce05
--- /dev/null
+++ b/src/sdl_generic.h
@@ -0,0 +1,11 @@
+#ifndef __SDL_GENERIC_H__
+#define __SDL_GENERIC_H__
+
+#include "common.h"
+
+#define MLTAG_PRESSED (-210416379)
+#define MLTAG_RELEASED (551170427)
+
+extern lookup_info ml_generic_button_table[];
+
+#endif /*__SDL_GENERIC_H__*/
diff --git a/src/sdl_input_trans.c b/src/sdl_input_trans.c
new file mode 100644
index 0000000..f39790d
--- /dev/null
+++ b/src/sdl_input_trans.c
@@ -0,0 +1,18 @@
+#include <caml/mlvalues.h>
+#include <SDL.h>
+
+#include "common.h"
+#include "sdl_input_trans.h"
+
+lookup_info ml_joyhat_trans_table[] = {
+{0, 9},
+{Val_int(MLTAG_HAT_CENTERED)  , SDL_HAT_CENTERED},
+{Val_int(MLTAG_HAT_UP)        , SDL_HAT_UP},
+{Val_int(MLTAG_HAT_RIGHT)     , SDL_HAT_RIGHT},
+{Val_int(MLTAG_HAT_DOWN)      , SDL_HAT_DOWN},
+{Val_int(MLTAG_HAT_LEFT)      , SDL_HAT_LEFT},
+{Val_int(MLTAG_HAT_RIGHTUP)   , SDL_HAT_RIGHTUP},
+{Val_int(MLTAG_HAT_RIGHTDOWN) , SDL_HAT_RIGHTDOWN},
+{Val_int(MLTAG_HAT_LEFTUP)    , SDL_HAT_LEFTUP},
+{Val_int(MLTAG_HAT_LEFTDOWN)  , SDL_HAT_LEFTDOWN}
+};
diff --git a/src/sdl_input_trans.h b/src/sdl_input_trans.h
new file mode 100644
index 0000000..0ec250d
--- /dev/null
+++ b/src/sdl_input_trans.h
@@ -0,0 +1,18 @@
+#ifndef __SDL_INPUT_TRANS_H__
+#define __SDL_INPUT_TRANS_H__
+
+#include "common.h"
+
+#define MLTAG_HAT_CENTERED  (0)
+#define MLTAG_HAT_UP        (1)
+#define MLTAG_HAT_RIGHT     (2)
+#define MLTAG_HAT_DOWN      (3)
+#define MLTAG_HAT_LEFT      (4)
+#define MLTAG_HAT_RIGHTUP   (5)
+#define MLTAG_HAT_RIGHTDOWN (6)
+#define MLTAG_HAT_LEFTUP    (7)
+#define MLTAG_HAT_LEFTDOWN  (8)
+
+extern lookup_info ml_joyhat_trans_table[];
+
+#endif /* __SDL_INPUT_TRANS_H__ */
diff --git a/src/sdl_key_trans.c b/src/sdl_key_trans.c
new file mode 100644
index 0000000..d5372bb
--- /dev/null
+++ b/src/sdl_key_trans.c
@@ -0,0 +1,141 @@
+#include "sdl_key_trans.h"
+
+#include <SDL.h>
+#include <SDL_keysym.h>
+
+lookup_info ml_symkey_trans_table[] = {
+{0, 133},
+{Val_int(MLTAG_SDLK_BACKSPACE), SDLK_BACKSPACE},
+{Val_int(MLTAG_SDLK_TAB), SDLK_TAB},
+{Val_int(MLTAG_SDLK_CLEAR), SDLK_CLEAR},
+{Val_int(MLTAG_SDLK_RETURN), SDLK_RETURN},
+{Val_int(MLTAG_SDLK_PAUSE), SDLK_PAUSE},
+{Val_int(MLTAG_SDLK_ESCAPE), SDLK_ESCAPE},
+{Val_int(MLTAG_SDLK_SPACE), SDLK_SPACE},
+{Val_int(MLTAG_SDLK_EXCLAIM), SDLK_EXCLAIM},
+{Val_int(MLTAG_SDLK_QUOTEDBL), SDLK_QUOTEDBL},
+{Val_int(MLTAG_SDLK_HASH), SDLK_HASH},
+{Val_int(MLTAG_SDLK_DOLLAR), SDLK_DOLLAR},
+{Val_int(MLTAG_SDLK_AMPERSAND), SDLK_AMPERSAND},
+{Val_int(MLTAG_SDLK_QUOTE), SDLK_QUOTE},
+{Val_int(MLTAG_SDLK_LEFTPAREN), SDLK_LEFTPAREN},
+{Val_int(MLTAG_SDLK_RIGHTPAREN), SDLK_RIGHTPAREN},
+{Val_int(MLTAG_SDLK_ASTERISK), SDLK_ASTERISK},
+{Val_int(MLTAG_SDLK_PLUS), SDLK_PLUS},
+{Val_int(MLTAG_SDLK_COMMA), SDLK_COMMA},
+{Val_int(MLTAG_SDLK_MINUS), SDLK_MINUS},
+{Val_int(MLTAG_SDLK_PERIOD), SDLK_PERIOD},
+{Val_int(MLTAG_SDLK_SLASH), SDLK_SLASH},
+{Val_int(MLTAG_SDLK_0), SDLK_0},
+{Val_int(MLTAG_SDLK_1), SDLK_1},
+{Val_int(MLTAG_SDLK_2), SDLK_2},
+{Val_int(MLTAG_SDLK_3), SDLK_3},
+{Val_int(MLTAG_SDLK_4), SDLK_4},
+{Val_int(MLTAG_SDLK_5), SDLK_5},
+{Val_int(MLTAG_SDLK_6), SDLK_6},
+{Val_int(MLTAG_SDLK_7), SDLK_7},
+{Val_int(MLTAG_SDLK_8), SDLK_8},
+{Val_int(MLTAG_SDLK_9), SDLK_9},
+{Val_int(MLTAG_SDLK_COLON), SDLK_COLON},
+{Val_int(MLTAG_SDLK_SEMICOLON), SDLK_SEMICOLON},
+{Val_int(MLTAG_SDLK_LESS), SDLK_LESS},
+{Val_int(MLTAG_SDLK_EQUALS), SDLK_EQUALS},
+{Val_int(MLTAG_SDLK_GREATER), SDLK_GREATER},
+{Val_int(MLTAG_SDLK_QUESTION), SDLK_QUESTION},
+{Val_int(MLTAG_SDLK_AT), SDLK_AT},
+{Val_int(MLTAG_SDLK_LEFTBRACKET), SDLK_LEFTBRACKET},
+{Val_int(MLTAG_SDLK_BACKSLASH), SDLK_BACKSLASH},
+{Val_int(MLTAG_SDLK_RIGHTBRACKET), SDLK_RIGHTBRACKET},
+{Val_int(MLTAG_SDLK_CARET), SDLK_CARET},
+{Val_int(MLTAG_SDLK_UNDERSCORE), SDLK_UNDERSCORE},
+{Val_int(MLTAG_SDLK_BACKQUOTE), SDLK_BACKQUOTE},
+{Val_int(MLTAG_SDLK_A), SDLK_a},
+{Val_int(MLTAG_SDLK_B), SDLK_b},
+{Val_int(MLTAG_SDLK_C), SDLK_c},
+{Val_int(MLTAG_SDLK_D), SDLK_d},
+{Val_int(MLTAG_SDLK_E), SDLK_e},
+{Val_int(MLTAG_SDLK_F), SDLK_f},
+{Val_int(MLTAG_SDLK_G), SDLK_g},
+{Val_int(MLTAG_SDLK_H), SDLK_h},
+{Val_int(MLTAG_SDLK_I), SDLK_i},
+{Val_int(MLTAG_SDLK_J), SDLK_j},
+{Val_int(MLTAG_SDLK_K), SDLK_k},
+{Val_int(MLTAG_SDLK_L), SDLK_l},
+{Val_int(MLTAG_SDLK_M), SDLK_m},
+{Val_int(MLTAG_SDLK_N), SDLK_n},
+{Val_int(MLTAG_SDLK_O), SDLK_o},
+{Val_int(MLTAG_SDLK_P), SDLK_p},
+{Val_int(MLTAG_SDLK_Q), SDLK_q},
+{Val_int(MLTAG_SDLK_R), SDLK_r},
+{Val_int(MLTAG_SDLK_S), SDLK_s},
+{Val_int(MLTAG_SDLK_T), SDLK_t},
+{Val_int(MLTAG_SDLK_U), SDLK_u},
+{Val_int(MLTAG_SDLK_V), SDLK_v},
+{Val_int(MLTAG_SDLK_W), SDLK_w},
+{Val_int(MLTAG_SDLK_X), SDLK_x},
+{Val_int(MLTAG_SDLK_Y), SDLK_y},
+{Val_int(MLTAG_SDLK_Z), SDLK_z},
+{Val_int(MLTAG_SDLK_DELETE), SDLK_DELETE},
+{Val_int(MLTAG_SDLK_KP0), SDLK_KP0},
+{Val_int(MLTAG_SDLK_KP1), SDLK_KP1},
+{Val_int(MLTAG_SDLK_KP2), SDLK_KP2},
+{Val_int(MLTAG_SDLK_KP3), SDLK_KP3},
+{Val_int(MLTAG_SDLK_KP4), SDLK_KP4},
+{Val_int(MLTAG_SDLK_KP5), SDLK_KP5},
+{Val_int(MLTAG_SDLK_KP6), SDLK_KP6},
+{Val_int(MLTAG_SDLK_KP7), SDLK_KP7},
+{Val_int(MLTAG_SDLK_KP8), SDLK_KP8},
+{Val_int(MLTAG_SDLK_KP9), SDLK_KP9},
+{Val_int(MLTAG_SDLK_KP_PERIOD), SDLK_KP_PERIOD},
+{Val_int(MLTAG_SDLK_KP_DIVIDE), SDLK_KP_DIVIDE},
+{Val_int(MLTAG_SDLK_KP_MULTIPLY), SDLK_KP_MULTIPLY},
+{Val_int(MLTAG_SDLK_KP_MINUS), SDLK_KP_MINUS},
+{Val_int(MLTAG_SDLK_KP_PLUS), SDLK_KP_PLUS},
+{Val_int(MLTAG_SDLK_KP_ENTER), SDLK_KP_ENTER},
+{Val_int(MLTAG_SDLK_KP_EQUALS), SDLK_KP_EQUALS},
+{Val_int(MLTAG_SDLK_UP), SDLK_UP},
+{Val_int(MLTAG_SDLK_DOWN), SDLK_DOWN},
+{Val_int(MLTAG_SDLK_RIGHT), SDLK_RIGHT},
+{Val_int(MLTAG_SDLK_LEFT), SDLK_LEFT},
+{Val_int(MLTAG_SDLK_INSERT), SDLK_INSERT},
+{Val_int(MLTAG_SDLK_HOME), SDLK_HOME},
+{Val_int(MLTAG_SDLK_END), SDLK_END},
+{Val_int(MLTAG_SDLK_PAGEUP), SDLK_PAGEUP},
+{Val_int(MLTAG_SDLK_PAGEDOWN), SDLK_PAGEDOWN},
+{Val_int(MLTAG_SDLK_F1), SDLK_F1},
+{Val_int(MLTAG_SDLK_F2), SDLK_F2},
+{Val_int(MLTAG_SDLK_F3), SDLK_F3},
+{Val_int(MLTAG_SDLK_F4), SDLK_F4},
+{Val_int(MLTAG_SDLK_F5), SDLK_F5},
+{Val_int(MLTAG_SDLK_F6), SDLK_F6},
+{Val_int(MLTAG_SDLK_F7), SDLK_F7},
+{Val_int(MLTAG_SDLK_F8), SDLK_F8},
+{Val_int(MLTAG_SDLK_F9), SDLK_F9},
+{Val_int(MLTAG_SDLK_F10), SDLK_F10},
+{Val_int(MLTAG_SDLK_F11), SDLK_F11},
+{Val_int(MLTAG_SDLK_F12), SDLK_F12},
+{Val_int(MLTAG_SDLK_F13), SDLK_F13},
+{Val_int(MLTAG_SDLK_F14), SDLK_F14},
+{Val_int(MLTAG_SDLK_F15), SDLK_F15},
+{Val_int(MLTAG_SDLK_NUMLOCK), SDLK_NUMLOCK},
+{Val_int(MLTAG_SDLK_CAPSLOCK), SDLK_CAPSLOCK},
+{Val_int(MLTAG_SDLK_SCROLLOCK), SDLK_SCROLLOCK},
+{Val_int(MLTAG_SDLK_RSHIFT), SDLK_RSHIFT},
+{Val_int(MLTAG_SDLK_LSHIFT), SDLK_LSHIFT},
+{Val_int(MLTAG_SDLK_RCTRL), SDLK_RCTRL},
+{Val_int(MLTAG_SDLK_LCTRL), SDLK_LCTRL},
+{Val_int(MLTAG_SDLK_RALT), SDLK_RALT},
+{Val_int(MLTAG_SDLK_LALT), SDLK_LALT},
+{Val_int(MLTAG_SDLK_RMETA), SDLK_RMETA},
+{Val_int(MLTAG_SDLK_LMETA), SDLK_LMETA},
+{Val_int(MLTAG_SDLK_LSUPER), SDLK_LSUPER},
+{Val_int(MLTAG_SDLK_RSUPER), SDLK_RSUPER},
+{Val_int(MLTAG_SDLK_MODE), SDLK_MODE},
+{Val_int(MLTAG_SDLK_HELP), SDLK_HELP},
+{Val_int(MLTAG_SDLK_PRINT), SDLK_PRINT},
+{Val_int(MLTAG_SDLK_SYSREQ), SDLK_SYSREQ},
+{Val_int(MLTAG_SDLK_BREAK), SDLK_BREAK},
+{Val_int(MLTAG_SDLK_MENU), SDLK_MENU},
+{Val_int(MLTAG_SDLK_POWER), SDLK_POWER},
+{Val_int(MLTAG_SDLK_EURO), SDLK_EURO}
+};
diff --git a/src/sdl_key_trans.h b/src/sdl_key_trans.h
new file mode 100644
index 0000000..8a3ff4e
--- /dev/null
+++ b/src/sdl_key_trans.h
@@ -0,0 +1,144 @@
+#ifndef __SDL_KEY_TRANS_H__
+#define __SDL_KEY_TRANS_H__
+
+#include <caml/mlvalues.h>
+#include "common.h"
+
+#define MLTAG_SDLK_BACKSPACE    (0)
+#define MLTAG_SDLK_TAB          (1)
+#define MLTAG_SDLK_CLEAR        (2)
+#define MLTAG_SDLK_RETURN       (3)
+#define MLTAG_SDLK_PAUSE        (4)
+#define MLTAG_SDLK_ESCAPE       (5)
+#define MLTAG_SDLK_SPACE        (6)
+#define MLTAG_SDLK_EXCLAIM      (7)
+#define MLTAG_SDLK_QUOTEDBL     (8)
+#define MLTAG_SDLK_HASH         (9)
+#define MLTAG_SDLK_DOLLAR       (10)
+#define MLTAG_SDLK_AMPERSAND    (11)
+#define MLTAG_SDLK_QUOTE        (12)
+#define MLTAG_SDLK_LEFTPAREN    (13)
+#define MLTAG_SDLK_RIGHTPAREN   (14)
+#define MLTAG_SDLK_ASTERISK     (15)
+#define MLTAG_SDLK_PLUS         (16)
+#define MLTAG_SDLK_COMMA        (17)
+#define MLTAG_SDLK_MINUS        (18)
+#define MLTAG_SDLK_PERIOD       (19)
+#define MLTAG_SDLK_SLASH        (20)
+#define MLTAG_SDLK_0            (21)
+#define MLTAG_SDLK_1            (22)
+#define MLTAG_SDLK_2            (23)
+#define MLTAG_SDLK_3            (24)
+#define MLTAG_SDLK_4            (25)
+#define MLTAG_SDLK_5            (26)
+#define MLTAG_SDLK_6            (27)
+#define MLTAG_SDLK_7            (28)
+#define MLTAG_SDLK_8            (29)
+#define MLTAG_SDLK_9            (30)
+#define MLTAG_SDLK_COLON        (31)
+#define MLTAG_SDLK_SEMICOLON    (32)
+#define MLTAG_SDLK_LESS         (33)
+#define MLTAG_SDLK_EQUALS       (34)
+#define MLTAG_SDLK_GREATER      (35)
+#define MLTAG_SDLK_QUESTION     (36)
+#define MLTAG_SDLK_AT           (37)
+#define MLTAG_SDLK_LEFTBRACKET  (38)
+#define MLTAG_SDLK_BACKSLASH    (39)
+#define MLTAG_SDLK_RIGHTBRACKET (40)
+#define MLTAG_SDLK_CARET        (41)
+#define MLTAG_SDLK_UNDERSCORE   (42)
+#define MLTAG_SDLK_BACKQUOTE    (43)
+#define MLTAG_SDLK_A            (44)
+#define MLTAG_SDLK_B            (45)
+#define MLTAG_SDLK_C            (46)
+#define MLTAG_SDLK_D            (47)
+#define MLTAG_SDLK_E            (48)
+#define MLTAG_SDLK_F            (49)
+#define MLTAG_SDLK_G            (50)
+#define MLTAG_SDLK_H            (51)
+#define MLTAG_SDLK_I            (52)
+#define MLTAG_SDLK_J            (53)
+#define MLTAG_SDLK_K            (54)
+#define MLTAG_SDLK_L            (55)
+#define MLTAG_SDLK_M            (56)
+#define MLTAG_SDLK_N            (57)
+#define MLTAG_SDLK_O            (58)
+#define MLTAG_SDLK_P            (59)
+#define MLTAG_SDLK_Q            (60)
+#define MLTAG_SDLK_R            (61)
+#define MLTAG_SDLK_S            (62)
+#define MLTAG_SDLK_T            (63)
+#define MLTAG_SDLK_U            (64)
+#define MLTAG_SDLK_V            (65)
+#define MLTAG_SDLK_W            (66)
+#define MLTAG_SDLK_X            (67)
+#define MLTAG_SDLK_Y            (68)
+#define MLTAG_SDLK_Z            (69)
+#define MLTAG_SDLK_DELETE       (70)
+#define MLTAG_SDLK_KP0          (71)
+#define MLTAG_SDLK_KP1          (72)
+#define MLTAG_SDLK_KP2          (73)
+#define MLTAG_SDLK_KP3          (74)
+#define MLTAG_SDLK_KP4          (75)
+#define MLTAG_SDLK_KP5          (76)
+#define MLTAG_SDLK_KP6          (77)
+#define MLTAG_SDLK_KP7          (78)
+#define MLTAG_SDLK_KP8          (79)
+#define MLTAG_SDLK_KP9          (80)
+#define MLTAG_SDLK_KP_PERIOD    (81)
+#define MLTAG_SDLK_KP_DIVIDE    (82)
+#define MLTAG_SDLK_KP_MULTIPLY  (83)
+#define MLTAG_SDLK_KP_MINUS     (84)
+#define MLTAG_SDLK_KP_PLUS      (85)
+#define MLTAG_SDLK_KP_ENTER     (86)
+#define MLTAG_SDLK_KP_EQUALS    (87)
+#define MLTAG_SDLK_UP           (88)
+#define MLTAG_SDLK_DOWN         (89)
+#define MLTAG_SDLK_RIGHT        (90)
+#define MLTAG_SDLK_LEFT         (91)
+#define MLTAG_SDLK_INSERT       (92)
+#define MLTAG_SDLK_HOME         (93)
+#define MLTAG_SDLK_END          (94)
+#define MLTAG_SDLK_PAGEUP       (95)
+#define MLTAG_SDLK_PAGEDOWN     (96)
+#define MLTAG_SDLK_F1           (97)
+#define MLTAG_SDLK_F2           (98)
+#define MLTAG_SDLK_F3           (99)
+#define MLTAG_SDLK_F4           (100)
+#define MLTAG_SDLK_F5           (101)
+#define MLTAG_SDLK_F6           (102)
+#define MLTAG_SDLK_F7           (103)
+#define MLTAG_SDLK_F8           (104)
+#define MLTAG_SDLK_F9           (105)
+#define MLTAG_SDLK_F10          (106)
+#define MLTAG_SDLK_F11          (107)
+#define MLTAG_SDLK_F12          (108)
+#define MLTAG_SDLK_F13          (109)
+#define MLTAG_SDLK_F14          (110)
+#define MLTAG_SDLK_F15          (111)
+#define MLTAG_SDLK_NUMLOCK      (112)
+#define MLTAG_SDLK_CAPSLOCK     (113)
+#define MLTAG_SDLK_SCROLLOCK    (114)
+#define MLTAG_SDLK_RSHIFT       (115)
+#define MLTAG_SDLK_LSHIFT       (116)
+#define MLTAG_SDLK_RCTRL        (117)
+#define MLTAG_SDLK_LCTRL        (118)
+#define MLTAG_SDLK_RALT         (119)
+#define MLTAG_SDLK_LALT         (120)
+#define MLTAG_SDLK_RMETA        (121)
+#define MLTAG_SDLK_LMETA        (122)
+#define MLTAG_SDLK_LSUPER       (123)
+#define MLTAG_SDLK_RSUPER       (124)
+#define MLTAG_SDLK_MODE         (125)
+#define MLTAG_SDLK_HELP         (126)
+#define MLTAG_SDLK_PRINT        (127)
+#define MLTAG_SDLK_SYSREQ       (128)
+#define MLTAG_SDLK_BREAK        (129)
+#define MLTAG_SDLK_MENU         (130)
+#define MLTAG_SDLK_POWER        (131)
+#define MLTAG_SDLK_EURO         (132)
+
+extern lookup_info ml_symkey_trans_table[];
+extern lookup_info ml_modkey_trans_table[];
+
+#endif /*__SDL_KEY_TRANS_H__*/
[from now] 2012/09/26 00:31:41

diff --git a/src/sdl_generic.h b/src/sdl_generic.h
index 01cce05..4108fcd 100644
--- a/src/sdl_generic.h
+++ b/src/sdl_generic.h
@@ -1,11 +1,11 @@
-#ifndef __SDL_GENERIC_H__
-#define __SDL_GENERIC_H__
-
-#include "common.h"
-
+#ifndef __SDL_GENERIC_H__
+#define __SDL_GENERIC_H__
+
+#include "common.h"
+
 #define MLTAG_PRESSED (-210416379)
-#define MLTAG_RELEASED (551170427)
-
-extern lookup_info ml_generic_button_table[];
-
-#endif /*__SDL_GENERIC_H__*/
+#define MLTAG_RELEASED (551170427)
+
+extern lookup_info ml_generic_button_table[];
+
+#endif /*__SDL_GENERIC_H__*/
diff --git a/src/sdl_input.ml b/src/sdl_input.ml
index aeba2bd..a15f5f7 100644
--- a/src/sdl_input.ml
+++ b/src/sdl_input.ml
@@ -49,7 +49,7 @@ type hat_state =
  * @param unit dummy argument
  * @return map for snapshot of the current keyboard state
  *)
-external get_key_state: ?num:int -> unit -> Sdl_key.state_map
+external get_key_state: unit -> Sdl_key.state_map
   = "sdlcaml_get_key_state"

 (**
diff --git a/src/sdl_key.ml b/src/sdl_key.ml
index 9666895..179b609 100644
--- a/src/sdl_key.ml
+++ b/src/sdl_key.ml
@@ -179,3 +179,14 @@ module StateMap = Map.Make (

 (** type of map for key associate to each button state *)
 type state_map = Sdl_generic.button_state StateMap.t
+
+(**
+   This function is provided to be used from C.
+   To reveive array is converted into {!state_map}.
+*)
+let to_state_map statearray =
+  let make_map map (key, state) = Map.add key state in
+  Array.fold_left make_map Map.empty statearray
+
+let () =
+  Callback.register "sdlcaml_ml_convert_state_map" to_state_map
diff --git a/src/sdl_key_trans.c b/src/sdl_key_trans.c
index d5372bb..20869c7 100644
--- a/src/sdl_key_trans.c
+++ b/src/sdl_key_trans.c
@@ -139,3 +139,19 @@ lookup_info ml_symkey_trans_table[] = {
 {Val_int(MLTAG_SDLK_POWER), SDLK_POWER},
 {Val_int(MLTAG_SDLK_EURO), SDLK_EURO}
 };
+
+lookup_info ml_modkey_trans_table = {
+  {0, 12},
+  {Val_int(MLTAG_KMOD_NONE), KMOD_NONE},
+  {Val_int(MLTAG_KMOD_NUM), KMOD_NUM},
+  {Val_int(MLTAG_KMOD_CAPS), KMOD_CAPS},
+  {Val_int(MLTAG_KMOD_LCTRL), KMOD_LCTRL},
+  {Val_int(MLTAG_KMOD_RCTRL), KMOD_RCTRL},
+  {Val_int(MLTAG_KMOD_RSHIFT), KMOD_RSHIFT},
+  {Val_int(MLTAG_KMOD_LSHIFT), KMOD_LSHIFT},
+  {Val_int(MLTAG_KMOD_RALT), KMOD_RALT},
+  {Val_int(MLTAG_KMOD_LALT), KMOD_LALT},
+  {Val_int(MLTAG_KMOD_CTRL), KMOD_CTRL},
+  {Val_int(MLTAG_KMOD_SHIFT), KMOD_SHIFT},
+  {Val_int(MLTAG_KMOD_ALT), KMOD_ALT}
+};
diff --git a/src/sdl_key_trans.h b/src/sdl_key_trans.h
index 8a3ff4e..9c0a61e 100644
--- a/src/sdl_key_trans.h
+++ b/src/sdl_key_trans.h
@@ -138,6 +138,21 @@
 #define MLTAG_SDLK_POWER        (131)
 #define MLTAG_SDLK_EURO         (132)

+/* modify key constants */
+#define MLTAG_KMOD_NONE         ( 0)
+#define MLTAG_KMOD_NUM          ( 1)
+#define MLTAG_KMOD_CAPS         ( 2)
+#define MLTAG_KMOD_LCTRL        ( 3)
+#define MLTAG_KMOD_RCTRL        ( 4)
+#define MLTAG_KMOD_RSHIFT       ( 5)
+#define MLTAG_KMOD_LSHIFT       ( 6)
+#define MLTAG_KMOD_RALT         ( 7)
+#define MLTAG_KMOD_LALT         ( 8)
+#define MLTAG_KMOD_CTRL         ( 9)
+#define MLTAG_KMOD_SHIFT        (10)
+#define MLTAG_KMOD_ALT          (11)
+
+
 extern lookup_info ml_symkey_trans_table[];
 extern lookup_info ml_modkey_trans_table[];
[from now] 2012/09/26 07:54:35

diff --git a/src/sdl_generic.c b/src/sdl_generic.c
new file mode 100644
index 0000000..9ae9644
--- /dev/null
+++ b/src/sdl_generic.c
@@ -0,0 +1,9 @@
+#include "common.h"
+
+#include "sdl_generic.h"
+
+lookup_info ml_generic_button_table = {
+  {0, 2}
+  {Val_int(MLTAG_PRESSED), 1}
+  {Val_int(MLTAG_RELEASED), 0}
+};
diff --git a/src/sdl_input_stub.c b/src/sdl_input_stub.c
new file mode 100644
index 0000000..81905a5
--- /dev/null
+++ b/src/sdl_input_stub.c
@@ -0,0 +1,42 @@
+#include <SDL.h>
+#include <caml/mlvalues.h>
+#include <caml/memory.h>
+#include <caml/alloc.h>
+#include <caml/callback.h>
+
+
+#include "common.h"
+#include "sdl_input_trans.h"
+
+CAMLprim value sdlcaml_get_key_state(value unit) {
+  CAMLparam0();
+
+  int numkey = 0;
+
+  Uint8* keystates = SDL_GetKeyState(&numkey);
+  CAMLlocal2(preconvert_array, tuple);
+  preconvert_array = caml_alloc(numkey, 0);
+
+  int key_trans_size = ml_table_size(ml_symkey_trans_table);
+  for (int i = 0; i < numkey && i < key_trans_size; ++i) {
+    tuple = caml_alloc(2, 0);
+
+    int current_key = ml_lookup_to_c(ml_symkey_trans_table, Val_int(i));
+    Store_field(tuple, 0, Val_int(i));
+    Store_field(tuple, 1, ml_lookup_from_c(
+        ml_generic_button_state_table, keystates[current_key]));
+
+    Store_field(preconvert_array, i, tuple);
+  }
+
+  /* convert to state_map with making use of callback function */
+  static value* converter = NULL;
+  if (converter == NULL) {
+    converter = caml_named_value("sdlcaml_ml_convert_state_map");
+  }
+  CAMLreturn(caml_callback(*converter, preconvert_array));
+}
+
+CAMLprim value get_mod_state(value unit) {
+
+}