add to sdl_video bindings and test for them.

Modify OCamlfiles to be more efficient build.
[from now] 2012/09/20 00:11:32

diff --git a/src/sdl_video.ml b/src/sdl_video.ml
index 0e574aa..8327e88 100644
--- a/src/sdl_video.ml
+++ b/src/sdl_video.ml
@@ -56,11 +56,17 @@ type pixelformat = {
 }

 (**
- * type of color that is synonym of {!int}.
- * this type is included some color for instance, Red, Green,
- * Blue, Alpha  or pixel color such as RGBA.
+ * type of color which is included each color elements and
+ * combined with of those.
+ * this type has appliable functions such a conversion
+ * colors, or split color to elements.
  *)
-type color = int
+type color = {
+  red:int;                              (* red attribute *)
+  blue:int;                             (* blue attribute *)
+  green:int;                            (* green attribute *)
+  alpha:int;                            (* transparently *)
+}

 (**
  * Binding of {i SDL_SetVideoMode}. if this function failed, raise
@@ -97,3 +103,40 @@ external sdl_free_surface: surface -> unit = "sdlcaml_free_surface"
  * @return valid pixelformat in a given surface
  *)
 external sdl_get_pixelformat: surface -> pixelformat = "sdlcaml_get_pixelformat"
+
+(** result of {!sdl_blit_surface} function. *)
+type blit_result =
+  BLIT_SUCCESS
+| BLIT_FAILURE
+| BLIT_LOST
+
+(**
+ * bliting clipped src surface with src rect to clippied dist surface
+ * by dist rect.
+ * When this function return BLIT_LOST, these should be reloaded with
+ * artwork or be redrew by some operation, and re-blitted.
+ *
+ * {!srect} and {!drect} are optional arguments. if these are not
+ * received some rectangle, there are used to {b NULL}.
+ *
+ * @param src source surface
+ * @param dist distination surface
+ * @param srect size of the copied rectangle
+ * @param drect position of the copied rectangle's upper left corner
+ * @return result of SDL_BlitSurface operation.
+ *)
+external sdl_blit_surface: src:surface -> dist:surface
+  -> ?srect:rect -> ?drect:rect -> blit_result = "sdlcaml_blit_surface"
+
+(**
+ * Fill of the given rectangle with some color.
+ * this function will fill the whole surface if you doesn't give {b
+ * drect}.
+ *
+ * @param dist distination surface
+ * @param fill filling color that should be a pixel of the format used
+ *             by the distination surface
+ * @param drect filling space of rectanble
+ *)
+external sdl_fill_color: dist:surface -> fill:color -> ?drect:rect ->
+  unit = "sdlcaml_fill_rect"
diff --git a/test/test_sdl_video.ml b/test/test_sdl_video.ml
new file mode 100644
index 0000000..8918c0e
--- /dev/null
+++ b/test/test_sdl_video.ml
@@ -0,0 +1,65 @@
+open Sdlcaml
+open OUnit
+
+let test_set_up _ =
+  begin
+    Sdl.sdl_init [`VIDEO];
+    sdl_set_video_mode ~width:640 ~height:480 ~depth:24
+      ~flags:[SDL_SWSURFACE];
+  end
+
+let test_tear_down surface =
+  begin
+    Sdl_video.sdl_free_surface surface;
+    Sdl.sdl_quit ();
+  end
+
+let test_sdl_video_init surface =
+  begin
+    Thread.delay 3.0;
+  end
+
+let test_sdl_get_pixel_format surface =
+  begin
+    let format = sdl_get_pixelformat surface in
+    assert_equal 24 format.bits_per_pixel;
+    assert_equal 3 format.bytes_per_pixel;
+    assert_equal 0xFF0000 format.rmask;
+    assert_equal 0xFF00 format.gmask;
+    assert_equal 0xFF format.bmask;
+  end
+
+let test_sdl_fill_color surface =
+  begin
+    let col = {red = 255; green = 128; blue = 0; alpha = 255} in
+    Sdl_video.sdl_fill_color ~dist:surface ~fill:col;
+    Thread.delay 5.0;
+  end
+
+let test_sdl_blit_surface surface =
+  begin
+    let newsurface = Sdl_video.sdl_create_surface
+      ~flags:[SDL_SWSURFACE;SDL_SRCALPHA] ~width:300 ~height:200
+    and col = {red = 255; green = 128; blue = 0; alpha = 255} in
+    Sdl_video.sdl_fill_color ~dist:newsurface ~fill:col;
+    Sdl_video.sdl_blit_surface ~src:newsurface ~dist:surface;
+    Thread.delay 3.0;
+    Sdl_video.sdl_free_surface newsurface;
+  end
+
+let test_sdl_get
+
+let suite = "SDL video tests" >:::
+  [ "video initialize" >:: (bracket test_set_up test_sdl_video_init
+                               test_tear_down);
+    "get current pixel format" >::
+      (bracket test_set_up test_sdl_get_pixel_format test_tear_down);
+    "fill color" >::
+      (bracket test_set_up test_sdl_fill_color test_tear_down);
+    "blit surface" >::
+      (bracket test_set_up test_sdl_blit_surface test_tear_down);
+
+  ]
+
+let _ =
+  run_test_tt_main suite
[from now] 2012/09/21 07:56:51

diff --git a/test/test_sdl_video.ml b/test/test_sdl_video.ml
index 8918c0e..b6bd791 100644
--- a/test/test_sdl_video.ml
+++ b/test/test_sdl_video.ml
@@ -4,8 +4,8 @@ open OUnit
 let test_set_up _ =
   begin
     Sdl.sdl_init [`VIDEO];
-    sdl_set_video_mode ~width:640 ~height:480 ~depth:24
-      ~flags:[SDL_SWSURFACE];
+    Sdl_video.sdl_set_video_mode ~width:640 ~height:480 ~depth:24
+      ~flags:[Sdl_video.SDL_SWSURFACE];
   end

 let test_tear_down surface =
@@ -21,7 +21,8 @@ let test_sdl_video_init surface =

 let test_sdl_get_pixel_format surface =
   begin
-    let format = sdl_get_pixelformat surface in
+    let format = Sdl_video.sdl_get_pixelformat surface in
+    let open Sdl_video in
     assert_equal 24 format.bits_per_pixel;
     assert_equal 3 format.bytes_per_pixel;
     assert_equal 0xFF0000 format.rmask;
@@ -31,24 +32,24 @@ let test_sdl_get_pixel_format surface =

 let test_sdl_fill_color surface =
   begin
+    let open Sdl_video in
     let col = {red = 255; green = 128; blue = 0; alpha = 255} in
-    Sdl_video.sdl_fill_color ~dist:surface ~fill:col;
+    Sdl_video.sdl_fill_color ~dist:surface ~fill:col ();
     Thread.delay 5.0;
   end

 let test_sdl_blit_surface surface =
   begin
+    let open Sdl_video in
     let newsurface = Sdl_video.sdl_create_surface
       ~flags:[SDL_SWSURFACE;SDL_SRCALPHA] ~width:300 ~height:200
     and col = {red = 255; green = 128; blue = 0; alpha = 255} in
-    Sdl_video.sdl_fill_color ~dist:newsurface ~fill:col;
-    Sdl_video.sdl_blit_surface ~src:newsurface ~dist:surface;
+    Sdl_video.sdl_fill_color ~dist:newsurface ~fill:col ();
+    assert_equal BLIT_SUCCESS (Sdl_video.sdl_blit_surface ~src:newsurface ~dist:surface ());
     Thread.delay 3.0;
     Sdl_video.sdl_free_surface newsurface;
   end

-let test_sdl_get
-
 let suite = "SDL video tests" >:::
   [ "video initialize" >:: (bracket test_set_up test_sdl_video_init
                                test_tear_down);
[from now] 2012/09/22 18:25:46

diff --git a/OMakefile b/OMakefile
index ccf7021..5725456 100644
--- a/OMakefile
+++ b/OMakefile
@@ -98,14 +98,16 @@ OCAMLOPTFLAGS +=
 # OCAML_LIB_FLAGS +=
 #
 LIBRARY_NAME = sdlcaml
-LIB = bin/sdlcaml
 #
-OCAML_PACKAGE_NAME = $(capitalize $(LIBRARY_NAME))

-.DEFAULT:
+.DEFAULT: src/sdlcaml$(EXT_LIB)
+
+
+.PHONY: test
+
+test: test/test$(EXE)

 clean:
-	rm -f $(ls src/*cmi src/*cmx src/*cmo src/*o src/*cmxa)
 	rm -f $(LIB).opt
 	rm -f $(LIB).run
 	rm -f $(LIB).a
diff --git a/config/OMakefile b/config/OMakefile
index 09d1455..4d10787 100644
--- a/config/OMakefile
+++ b/config/OMakefile
@@ -85,20 +85,9 @@ sdl_initflags.h: initflag$(EXE) sdl_initflags.h.in

 initflag$(EXE): outputflag.c initflag.ml
 	$(OCAMLC) -ccopt "$(PREFIXED_INCLUDES)" -o $(addsuffix $(EXT_OBJ), $(removesuffix $<)) -c $<
-	$(OCAMLMKLIB) -o $@ $(addsuffix $(EXT_OBJ), $(removesuffix $<))
+	$(OCAMLMKLIB) -o $(removesuffix $@) $(addsuffix $(EXT_OBJ), $(removesuffix $<))
 	$(OCAMLOPT) -o $@ $(nth 1, $+) -cclib "$(absname lib$(removesuffix $@)$(EXT_LIB))"

-videoflag$(EXE): outputflag.c videoflag.ml
-	$(OCAMLC) -ccopt "$(PREFIXED_INCLUDES)" -o $(addsuffix $(EXT_OBJ), $(removesuffix $<)) -c $<
-	$(OCAMLMKLIB) -o $@ $(addsuffix $(EXT_OBJ), $(removesuffix $<))
-	$(OCAMLOPT) -o $@ $(nth 1, $+) -cclib "$(absname lib$(removesuffix $@)$(EXT_LIB))"
-
-sdl_video_flags.h: videoflag$(EXE) sdl_video_flags.h.in
-	section
-		flags = $(concat \\n, $(shella $<))
-		sed -e "s/#FLAGS/$(flags)/" $(nth 1, $+) > $@
-		cp $@ ../src/$@
-
 #
 # OCAML_LIBS += ../lib/mylib
 # OCAML_CLIBS +=
@@ -106,7 +95,7 @@ sdl_video_flags.h: videoflag$(EXE) sdl_video_flags.h.in
 # OCAML_LIB_FLAGS +=
 # OCAML_PACKAGE_NAME =
 #
-.DEFAULT: sdl_initflags.h sdl_video_flags.h
+.DEFAULT: sdl_initflags.h

 .PHONY: clean

@@ -117,6 +106,4 @@ clean:
 	rm -f *.cmi
 	rm -f *.cmx
 	rm -f sdl_initflags.h
-	rm -f sdl_video_flags.h
 	rm -f initflag$(EXE)
-	rm -f videoflag$(EXE)
diff --git a/config/sdl_video_flags.h b/config/sdl_video_flags.h
deleted file mode 100644
index e375b43..0000000
--- a/config/sdl_video_flags.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef __SDL_VIDEO_FLAGS_H__
-#define __SDL_VIDEO_FLAGS_H__
-
-#include "common.h"
-
-#define MLTAG_SDL_SWSURFACE (-957980661)
-#define MLTAG_SDL_HWSURFACE (640113141)
-#define MLTAG_SDL_ASYNCBLIT (-500945189)
-#define MLTAG_SDL_ANYFORMAT (658254399)
-#define MLTAG_SDL_HWPALETTE (-1000623471)
-#define MLTAG_SDL_DOUBLEBUF (102454653)
-#define MLTAG_SDL_FULLSCREEN (-790705857)
-#define MLTAG_SDL_OPENGL (999917991)
-#define MLTAG_SDL_OPENGLBLIT (-842377967)
-#define MLTAG_SDL_RESIZABLE (757699279)
-#define MLTAG_SDL_HWACCEL (332137195)
-#define MLTAG_SDL_SRCCOLORKEY (787865593)
-#define MLTAG_SDL_RLEACCEL (151829507)
-#define MLTAG_SDL_SRCALPHA (-520137027)
-#define MLTAG_SDL_PREALLOC (590878125)
-
-extern lookup_info ml_video_flag_table[];
-
-#endif /*__SDL_VIDEO_FLAGS_H__*/
diff --git a/config/sdl_video_flags.h.in b/config/sdl_video_flags.h.in
deleted file mode 100644
index ac52888..0000000
--- a/config/sdl_video_flags.h.in
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __SDL_VIDEO_FLAGS_H__
-#define __SDL_VIDEO_FLAGS_H__
-
-#include "common.h"
-
-#FLAGS
-
-extern lookup_info ml_video_flag_table[];
-
-#endif /*__SDL_VIDEO_FLAGS_H__*/
diff --git a/config/videoflag.ml b/config/videoflag.ml
deleted file mode 100644
index 533453e..0000000
--- a/config/videoflag.ml
+++ /dev/null
@@ -1,26 +0,0 @@
-let variants = [
-  "SDL_SWSURFACE";
-  "SDL_HWSURFACE";
-  "SDL_ASYNCBLIT";
-  "SDL_ANYFORMAT";
-  "SDL_HWPALETTE";
-  "SDL_DOUBLEBUF";
-  "SDL_FULLSCREEN";
-  "SDL_OPENGL";
-  "SDL_OPENGLBLIT";
-  "SDL_RESIZABLE";
-  "SDL_HWACCEL";
-  "SDL_SRCCOLORKEY";
-  "SDL_RLEACCEL";
-  "SDL_SRCALPHA";
-  "SDL_PREALLOC";
-]
-
-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/omakescripts/MyOCaml.om b/omakescripts/MyOCaml.om
index dde0e98..58dbb16 100644
--- a/omakescripts/MyOCaml.om
+++ b/omakescripts/MyOCaml.om
@@ -67,12 +67,7 @@ public.OCAML_LINK_FLAGS = $`(if $(and $(USE_OCAMLFIND) $(gt $(length $(OCAMLPACK
 public.OCAML_BYTE_LINK_FLAGS = -custom
 public.OCAML_NATIVE_LINK_FLAGS =
 # ocaml packaging option
-public.OCAML_PACKAGE_NAME =
-public.PREFIXED_OCAML_PACKAGE_FLAG() =
-    if $(and $(gt $(string-length $(OCAML_PACKAGE_NAME)), 0), $(NATIVE_ENABLED))
-        return -for-pack $(OCAML_PACKAGE_NAME)
-    else
-        return $(EMPTY)
+OCAML_PACKAGE_FLAG =

 public.LocalOCamlGeneratedFiles(files) =
     if $(OCAMLDEP_MODULES_ENABLED)
@@ -288,12 +283,12 @@ OCamlLinkSort(nodes) =

 # generic OCaml compile function.
 public.OCamlC() =
-    return $(OCAMLFIND) $(OCAMLC) $(LAZY_OCAMLFINDFLAGS) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS)\
-              $(OCAMLCFLAGS) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES)
+    value $(OCAMLFIND) $(OCAMLC) $(LAZY_OCAMLFINDFLAGS) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS)\
+              $(OCAMLCFLAGS) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) $(OCAML_PACKAGE_FLAG)

 public.OCamlOpt() =
-    return $(OCAMLFIND) $(OCAMLOPT) $(LAZY_OCAMLFINDFLAGS) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS)\
-              $(OCAMLOPTFLAGS) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) $(PREFIXED_OCAML_PACKAGE_FLAG)
+    value $(OCAMLFIND) $(OCAMLOPT) $(LAZY_OCAMLFINDFLAGS) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS)\
+              $(OCAMLOPTFLAGS) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) $(OCAML_PACKAGE_FLAG)

 %.cmx : %.ml
     section rule
@@ -381,6 +376,9 @@ if you really want to build this file.
 %.cmi: %.mli :scanner: scan-ocaml-%.mli
     $(OCamlC) -c $<

+# build rules
+# ======================================================================
+
 public.OCamlProgram(name, files) =
    # XXX: JYH: these variables should be marked private in 0.9.9
    protected.CMOFILES  = $(addsuffix .cmo, $(files))
@@ -429,9 +427,19 @@ public.OCamlProgram(name, files) =

    return $(array $(PROG), $(if $(NATIVE_ENABLED), $(OPTPROG)), $(if $(BYTE_ENABLED), $(BYTEPROG)))

+# Add rules to build OCaml library $(name)
+#    name
+#        name of the library
+#    files
+#        OCaml module names (without .ml)
+#
+#   .. note :: Probably you should use MyOCamlPackage
+MyOCamlLibrary(library, files) =
+   install-lib: $(OCamlLibrary $(library), $(files))
+   AutoClean()

 # build library with targets. this function returns between one and three file names.
-OCamlMakeLibrary(library, targets) =
+OCamlLibrary(library, targets) =
     protected.name = $(file $(library))

     protected.OFILES = $(addsuffix $(EXT_OBJ), $(targets))
@@ -451,8 +459,66 @@ OCamlMakeLibrary(library, targets) =
                 $(OCAML_LIB_FLAGS) -a -o $(NATIVELIB) $(OCamlLinkSort $(CMXFILES))
     return $(array $(if $(NATIVE_ENABLED), $(NATIVELIB)), $(if $(NATIVE_ENABLED), $(CLIB)), $(if $(BYTE_ENABLED), $(BYTELIB)))

+# Add a rule for OCaml package $(name).cmo, $(name).cmx and etc.
+#    name
+#        target package name
+#    files
+#        ML module names (without .ml)
+#    cmodules
+#        C source files (without .c)
+#    linkopts
+#        C library link option (without OCaml -cclib options)
+#
+# Example:
+#     MyOCamlPackage(foo, alpha beta, $(EMPTY), $(EMPTY))
+public.MyOCamlPackage(name, files, cmodules, linkopts) =
+
+   CSTUBS=$(addsuffix $(EXT_OBJ), $(cmodules))
+   protected.OFILES   = $(addsuffix $(EXT_OBJ), $(files))
+   protected.CMOFILES = $(addsuffix .cmo, $(files))
+   protected.CMXFILES = $(addsuffix .cmx, $(files))
+
+   protected.CMO       = $(file $(name).cmo)
+   protected.CMX       = $(file $(name).cmx)
+   protected.CMA       = $(file $(name).cma)
+   protected.CMXA      = $(file $(name).cmxa)
+
+   CSTUBLIBRARIES=
+   if $(not $(equal $(cmodules), $(EMPTY))) then
+       CSTUBLIBRARIES= dll$(name).so lib$(name)$(EXT_LIB)
+       export
+
+   # add a rule for install this package.
+   .PHONY: install-lib
+   install-lib: $(CMO) $(CMX) $(CMA) $(CMXA)
+
+   $(CMA) $(CMXA) $(name)$(EXT_LIB) $(CSTUBLIBRARIES): $(CSTUBS) $(CMO) $(CMX)
+       if $(not $(equal $(cmodules), $(EMPTY)))
+           ocamlmklib -verbose -o $(name) $(CSTUBS) $(linkopts) $(CMO) $(CMX)
+       else
+           $(OCamlC) -a -o $(CMA) $(CMO)
+           $(OCamlCOpt) -a -o $(CMXA) $(CMX)
+
+   # the followings are nessesary for packing
+   OCAML_PACKAGE_FLAG = -for-pack $(capitalize $(name))
+   export OCAML_PACKAGE_FLAG
+
+   # add a rule for clean
+   AutoClean()
+
+   # build rule for package
+   OCamlPackage($(name), $(files))
+
+   export
+
+# Add some rules for buidling OCaml package.
+#   name
+#       target package name
+#   files
+#       ML modules name (without .ml)
 public.OCamlPackage(name, files) =
    # XXX: JYH: these variables should be marked private in 0.9.9
+
    protected.OFILES   = $(addsuffix $(EXT_OBJ), $(files))
    protected.CMOFILES = $(addsuffix .cmo, $(files))
    protected.CMXFILES = $(addsuffix .cmx, $(files))
diff --git a/omakescripts/common/Function.om b/omakescripts/common/Function.om
index 20d205a..084e805 100644
--- a/omakescripts/common/Function.om
+++ b/omakescripts/common/Function.om
@@ -1,4 +1,4 @@
-RequireFiles(files) =
+RequiredFiles(files) =
     .SCANNER: scan-%: $(files)
     % : $(files)
     export
@@ -9,6 +9,13 @@ CreateCheckSum(pack, targets) =
     fprintln($(chan), $(string $(digest $(targets))))
     close($(chan))

+# Install clean command which cleans all the target files exists under
+# the directory. Use with care.
+AutoClean() =
+	.PHONY: clean
+	clean:
+		rm -f $(filter-proper-targets $(ls R, .))
+
 RequireBuild(targets) =
     dependencies.md5: $(targets)
         println($(string $(sequence-sort $(compare), $(dependencies-all $(targets)))))
diff --git a/src/OMakefile b/src/OMakefile
index 172a5d9..dae0117 100644
--- a/src/OMakefile
+++ b/src/OMakefile
@@ -22,8 +22,7 @@
 # Configuration.  You may want to modify any of these configuration
 # variables.
 #
-open MyOCaml
-open configure/Configure
+open common/Function
 open build/C

 #
@@ -51,7 +50,7 @@ if $(not $(OCAMLFIND_EXISTS))
 # The default values are defined as follows:
 #
 NATIVE_ENABLED = $(OCAMLOPT_EXISTS)
-BYTE_ENABLED = $(not $(OCAMLOPT_EXISTS))
+BYTE_ENABLED = true

 #
 # Various options
@@ -75,8 +74,6 @@ OCAMLFLAGS    += -annot
 # Build bindings for OCaml to C.
 #

-INCLUDES += /usr/include/caml
-
 # check that can sdl-config use.
 .STATIC:
 	SDL_CONFIG_FOUND = $(ConfMsgFound $(CheckProg sdl-config))
@@ -88,21 +85,15 @@ INCLUDES += /usr/include/caml
 	SDL_CONFIGURE = $(shell $(SDL_CONFIG) --libs --cflags)
 	export

-lib%$(EXT_LIB): %$(EXT_OBJ)
-	$(OCAMLMKLIB) -verbose -o $(removesuffix $<) $<
+CFILES = $(removesuffix $(ls *.c))

 %$(EXT_OBJ): %.c :scanner: scan-c-%.c
-# build with ocamlc with options from sdl-config.
-	$(OCAMLC) -ccopt "$(SDL_CONFIGURE) $(PREFIXED_INCLUDES)" -verbose -o $@ -c $<
+	$(OCAMLC) -ccopt "$(SDL_CONFIGURE)" -verbose -o $@ -c $<

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

 LIBRARY_NAME = sdlcaml
 #
-OCAML_PACKAGE_NAME = $(capitalize $(LIBRARY_NAME))
-packages = $(OCamlPackage $(LIBRARY_NAME), $(FILES))
-
-CFILES = $(removesuffix $(ls *.c))
 STATICLIBS = $(add-wrapper lib, $(EXT_LIB), $(CFILES))

 #
@@ -113,19 +104,8 @@ OCAML_LIB_FLAGS += -cclib "$(addprefix $(absname $(CWD))/, $(STATICLIBS))"
 OCAML_LIB_FLAGS += -verbose
 # OCAML_PACKAGE_NAME =
 #
-.PHONY: clean mainlib static_libs
-
-.DEFAULT: static_libs mainlib
-
-static_libs: $(STATICLIBS)
+RequiredFiles(../config/sdl_initflags.h)

-mainlib: $(OCamlMakeLibrary $(LIBRARY_NAME), $(removesuffix $(packages)))
+MyOCamlPackage($(LIBRARY_NAME), $(FILES), $(CFILES), $(EMPTY))

-clean:
-	rm -f *$(EXT_OBJ)
-	rm -f lib*$(EXT_LIB)
-	rm -f sdlcaml*
-	rm -f *cmx
-	rm -f *cmi
-	rm -f *so
-	rm -f *annot
+.DEFAULT: sdlcaml.cmxa
diff --git a/src/common.c b/src/common.c
index d5201b4..b705450 100644
--- a/src/common.c
+++ b/src/common.c
@@ -58,3 +58,13 @@ CAMLprim value tail(value list) {
 int is_not_nil(value list) {
   return (list != Val_emptylist);
 }
+
+/****************************************************/
+
+int is_none(value opt) {
+  return opt == Val_int(0);
+}
+
+int is_some(value opt) {
+  return !is_none(opt);
+}
diff --git a/src/common.h b/src/common.h
index 9e47050..9119156 100644
--- a/src/common.h
+++ b/src/common.h
@@ -8,9 +8,9 @@ typedef struct lookup_info {
   int value;
 } lookup_info;

-/**
- * lookup from key of OCaml to value of C, or from value of C to key OCaml
- * To be able to receive table is constructed that first is key equal zero and
+/**
+ * lookup from key of OCaml to value of C, or from value of C to key OCaml
+ * To be able to receive table is constructed that first is key equal zero and
  * value is length of table without itself.
  */
 int ml_lookup_to_c(lookup_info *table, value key);
@@ -21,5 +21,10 @@ value head(value list);
 value tail(value list);
 int is_not_nil(value list);

-#endif /* __COMMON_H__ */
+/** operations for 'a option */
+/* if given value is none, return 1.a*/
+int is_none(value opt);
+/* if given value is some, return 1.a*/
+int is_some(value opt);

+#endif /* __COMMON_H__ */
diff --git a/src/sdl.ml b/src/sdl.ml
index 5104ea2..89d19fa 100644
--- a/src/sdl.ml
+++ b/src/sdl.ml
@@ -15,6 +15,8 @@ type subsystem = [
   | `JOYSTICK
 ]

+exception Sdl_init_exception of string
+
 (** Initializing SDL and SDL Subsystems for SDK version of 1.2
  *  Taking arguments to this function have to {e flags}. if {e auto_clean} isn't
  *  send, you must call {!sdl_quit} in the end of your program.
diff --git a/src/sdl_stub.c b/src/sdl_stub.c
index 3fc2441..200fbb5 100644
--- a/src/sdl_stub.c
+++ b/src/sdl_stub.c
@@ -24,14 +24,23 @@ static int ml_make_init_flag(value flags) {
   return flag;
 }

+static void sdlcaml_inner_quit(void) {
+  SDL_Quit();
+}
+
 CAMLprim value sdlcaml_init(value auto_clean, value flags) {
   int init_flag = ml_make_init_flag(flags);

-  return Val_unit;
-}
+  if (SDL_Init(init_flag) < 0) {
+    caml_raise_with_string(caml_named_value("SDL_init_exception"),
+                           SDL_GetError());
+  }

-static void sdlcaml_inner_quit(void) {
-  SDL_Quit();
+  if (is_none(auto_clean)) {
+    atexit(sdlcaml_inner_quit);
+  }
+
+  return Val_unit;
 }

 CAMLprim value sdlcaml_quit(value unit) {
diff --git a/src/sdl_video.ml b/src/sdl_video.ml
index 8327e88..b1e86b6 100644
--- a/src/sdl_video.ml
+++ b/src/sdl_video.ml
@@ -31,6 +31,8 @@ type videomodes =
 | SDL_SRCALPHA     (** Surface blit uses alpha blending *)
 | SDL_PREALLOC     (** Surface uses preallocated memory *)

+exception Sdl_video_exception of string
+
 (**
  * Binding of {i SDL_Surface} but always hiding inner structure of
  * SDL_Surface.
@@ -65,7 +67,19 @@ type color = {
   red:int;                              (* red attribute *)
   blue:int;                             (* blue attribute *)
   green:int;                            (* green attribute *)
-  alpha:int;                            (* transparently *)
+  alpha:int;                            (* transparency *)
+}
+
+(**
+ * type of binding to {b SDL_Rect}. Each fields of this type has
+ * equivalent name of SDL_Rect's member.
+
+ *)
+type rect = {
+  x:int;                                (* left of left top corner *)
+  y:int;                                (* top of left top corner *)
+  w:int;                                (* rectangle width *)
+  h:int;                                (* rectangle height *)
 }

 (**
@@ -102,7 +116,8 @@ external sdl_free_surface: surface -> unit = "sdlcaml_free_surface"
  * functions
  * @return valid pixelformat in a given surface
  *)
-external sdl_get_pixelformat: surface -> pixelformat = "sdlcaml_get_pixelformat"
+external sdl_get_pixelformat: surface -> pixelformat =
+ "sdlcaml_get_pixelformat"

 (** result of {!sdl_blit_surface} function. *)
 type blit_result =
@@ -126,7 +141,7 @@ type blit_result =
  * @return result of SDL_BlitSurface operation.
  *)
 external sdl_blit_surface: src:surface -> dist:surface
-  -> ?srect:rect -> ?drect:rect -> blit_result = "sdlcaml_blit_surface"
+  -> ?srect:rect -> ?drect:rect -> unit -> blit_result = "sdlcaml_blit_surface"

 (**
  * Fill of the given rectangle with some color.
@@ -138,5 +153,51 @@ external sdl_blit_surface: src:surface -> dist:surface
  *             by the distination surface
  * @param drect filling space of rectanble
  *)
-external sdl_fill_color: dist:surface -> fill:color -> ?drect:rect ->
+external sdl_fill_rect: dist:surface -> fill:color -> ?drect:rect ->
+  unit ->
   unit = "sdlcaml_fill_rect"
+
+(**
+ * Return new surface created that of size is given width and height
+ * and with initialization flags.
+ * Depth of returning surface from this function is always 32-bits,
+ * I mean, always create surface that have ARGB format.
+ * If you create surface by this function, you have to apply
+ * {!sdl_free_surface} to it.
+ *
+ * @param width number of width pixels in surface
+ * @param height number of height pixels in surface
+ * @param flags initialization flag list
+ * @return created new surface
+ *)
+external sdl_create_surface: width:int -> height:int ->
+  flags:videomodes list -> surface = "sdlcaml_create_surface"
+
+(**
+ * update rectangle area on surface. It is nessesity from arguments that
+ * is only {b screen}.
+ * If all arguments omitted, update all area of given surface.
+ * Any optional arguments given, use it but other arguments used by
+ * default.
+ *
+ * @param x rectangle's left upper corner of left. default is 0.
+ * @param y rectangle's left upper corner of upper. defautl is 0.
+ * @param w width of rectangle. default is width of screen.
+ * @param h height of rectangle. default is height of screen.
+ * @param screen surface to update
+ *)
+external sdl_update_rect: ?x:int -> ?y:int ->
+  ?width:int -> ?height:int -> surface -> unit = "sdlcaml_update_rect"
+
+(**
+ * Swap screen buffers. The {!SDL_DOUBLEBUF} flags must have been
+ * passed to {!sdl_set_video_mode}.
+ * This function perform hardware flipping if hardware support
+ * double-buffering.
+ * On hardware that doesn't support double-buffering, this is
+ * equivalent to calling {!sdl_update_rect} with default.
+ *
+ * @param surface surface that is screen
+ * @raise Sdl_video_function When function fail
+ *)
+external sdl_flip: surface -> unit = "sdlcaml_flip"
diff --git a/src/sdl_video_flags.h b/src/sdl_video_flags.h
index e375b43..7bc61b5 100644
--- a/src/sdl_video_flags.h
+++ b/src/sdl_video_flags.h
@@ -3,21 +3,21 @@

 #include "common.h"

-#define MLTAG_SDL_SWSURFACE (-957980661)
-#define MLTAG_SDL_HWSURFACE (640113141)
-#define MLTAG_SDL_ASYNCBLIT (-500945189)
-#define MLTAG_SDL_ANYFORMAT (658254399)
-#define MLTAG_SDL_HWPALETTE (-1000623471)
-#define MLTAG_SDL_DOUBLEBUF (102454653)
-#define MLTAG_SDL_FULLSCREEN (-790705857)
-#define MLTAG_SDL_OPENGL (999917991)
-#define MLTAG_SDL_OPENGLBLIT (-842377967)
-#define MLTAG_SDL_RESIZABLE (757699279)
-#define MLTAG_SDL_HWACCEL (332137195)
-#define MLTAG_SDL_SRCCOLORKEY (787865593)
-#define MLTAG_SDL_RLEACCEL (151829507)
-#define MLTAG_SDL_SRCALPHA (-520137027)
-#define MLTAG_SDL_PREALLOC (590878125)
+#define MLTAG_SDL_SWSURFACE (0)
+#define MLTAG_SDL_HWSURFACE (1)
+#define MLTAG_SDL_ASYNCBLIT (2)
+#define MLTAG_SDL_ANYFORMAT (3)
+#define MLTAG_SDL_HWPALETTE (4)
+#define MLTAG_SDL_DOUBLEBUF (5)
+#define MLTAG_SDL_FULLSCREEN (6)
+#define MLTAG_SDL_OPENGL (7)
+#define MLTAG_SDL_OPENGLBLIT (8)
+#define MLTAG_SDL_RESIZABLE (9)
+#define MLTAG_SDL_HWACCEL (10)
+#define MLTAG_SDL_SRCCOLORKEY (11)
+#define MLTAG_SDL_RLEACCEL (12)
+#define MLTAG_SDL_SRCALPHA (13)
+#define MLTAG_SDL_PREALLOC (14)

 extern lookup_info ml_video_flag_table[];

diff --git a/src/sdl_video_stub.c b/src/sdl_video_stub.c
index 28ffd38..6082ffd 100644
--- a/src/sdl_video_stub.c
+++ b/src/sdl_video_stub.c
@@ -13,7 +13,7 @@ static int ml_make_video_setting_flag(value flags) {
   int flag = 0;

   while (is_not_nil(list)) {
-    int converted_tag = ml_lookup_to_c(ml_video_flag_table, head(list));
+    int converted_tag = ml_lookup_to_c(ml_video_flag_table, Int_val(head(list)));
     flag |= converted_tag;
     list = tail(list);
   }
@@ -64,3 +64,131 @@ CAMLprim value sdlcaml_get_pixelformat(value surface) {

   return pixelformat;
 }
+
+CAMLprim value sdlcaml_blit_surface(value src, value dist, value srect, value drect) {
+  SDL_Rect src_rect = {0,0,0,0};
+  SDL_Rect dist_rect = {0,0,0,0};
+  SDL_Rect *srectp = NULL, *drectp = NULL;
+
+  if (is_some(srect)) {
+    value extracted = Field(srect, 0);
+    src_rect.x = Field(extracted, 0);
+    src_rect.y = Field(extracted, 1);
+    src_rect.w = Field(extracted, 2);
+    src_rect.h = Field(extracted, 3);
+    srectp = &src_rect;
+  }
+
+  if (is_some(drect)) {
+    value extracted = Field(drect, 0);
+    dist_rect.x = Field(extracted, 0);
+    dist_rect.y = Field(extracted, 1);
+    dist_rect.w = Field(extracted, 2);
+    dist_rect.h = Field(extracted, 3);
+    drectp = &dist_rect;
+  }
+
+  int blit_result = SDL_BlitSurface((SDL_Surface*)src,
+                                    srectp,
+                                    (SDL_Surface*)dist,
+                                    drectp);
+  switch (blit_result) {
+    case -1: return Val_int(1);         /* Failed */
+    case -2: return Val_int(2);         /* Surface Lost */
+    default: return Val_int(0);         /* Success */
+  }
+}
+
+CAMLprim value sdlcaml_fill_rect(value dist, value fill, value drect) {
+  SDL_Rect dist_rect = {0,0,0,0};
+  SDL_Rect *dist_rectp = NULL;
+
+  if (is_some(drect)) {
+    dist_rect.x = Field(drect, 0);
+    dist_rect.y = Field(drect, 1);
+    dist_rect.w = Field(drect, 2);
+    dist_rect.h = Field(drect, 3);
+    dist_rectp = &dist_rect;
+  }
+
+  SDL_PixelFormat* format = ((SDL_Surface*)dist)->format;
+
+  Uint32 color =
+      Int_val(Field(fill, 0)) << format->Rshift |
+      Int_val(Field(fill, 1)) << format->Gshift |
+      Int_val(Field(fill, 2)) << format->Bshift |
+      Int_val(Field(fill, 3)) << format->Ashift;
+
+  SDL_FillRect((SDL_Surface*)dist, dist_rectp, color);
+
+  return Val_unit;
+}
+
+
+CAMLprim value sdlcaml_create_surface(value width, value height,
+                                      value flags) {
+  const int depth = 32;
+  int surface_width = Int_val(width);
+  int surface_height = Int_val(height);
+
+  /* add SDL_SRCALPHA always. */
+  int init_flag = ml_make_video_setting_flag(flags) | SDL_SRCALPHA;
+  int rmask, gmask, bmask, amask;
+
+  /* decide masks to depend on current endian  */
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+  rmask = 0xff000000;
+  gmask = 0x00ff0000;
+  bmask = 0x0000ff00;
+  amask = 0x000000ff;
+#else
+  rmask = 0x000000ff;
+  gmask = 0x0000ff00;
+  bmask = 0x00ff0000;
+  amask = 0xff000000;
+#endif
+
+  SDL_Surface* surface = SDL_CreateRGBSurface(init_flag,
+      surface_width, surface_height, depth,
+      rmask, gmask, bmask, amask);
+  if (surface == NULL) {
+    caml_raise_with_string(caml_named_value("SDL_video_exception"),
+                           SDL_GetError());
+  }
+  return (value)surface;
+}
+
+CAMLprim value sdlcaml_update_rect(value ox, value oy,
+                                   value owidth, value oheight, value surface) {
+  int x = 0, y = 0;
+  SDL_Surface* screen = (SDL_Surface*)surface;
+
+  int w = screen->w, h = screen->h;
+
+  if (is_some(ox)) {
+    x = Int_val(Field(ox, 0));
+  }
+
+  if (is_some(oy)) {
+    y = Int_val(Field(oy, 0));
+  }
+
+  if (is_some(owidth)) {
+    w = Int_val(Field(owidth, 0));
+  }
+
+  if (is_some(oheight)) {
+    h = Int_val(Field(oheight, 0));
+  }
+
+  SDL_UpdateRect(screen, x, y, w, h);
+}
+
+CAMLprim value sdlcaml_flip(value surface) {
+  if (SDL_Flip((SDL_Surface*)surface)) {
+    caml_raise_with_string(caml_named_value("SDL_video_exception"),
+                           SDL_GetError());
+  }
+
+  return Val_unit;
+}
diff --git a/test/OMakefile b/test/OMakefile
index 50f10c8..6afa9c5 100644
--- a/test/OMakefile
+++ b/test/OMakefile
@@ -22,7 +22,7 @@
 # Configuration.  You may want to modify any of these configuration
 # variables.
 #
-open MyOCaml
+open common/Function

 #
 # This project requires ocamlfind (default - false).
@@ -57,7 +57,8 @@ BYTE_ENABLED = $(not $(OCAMLOPT_EXISTS))
 OCAMLFLAGS    += -annot -thread
 # OCAMLCFLAGS   +=
 # OCAMLOPTFLAGS +=
-OCAML_LINK_FLAGS += -cclib "$(shell sdl-config --libs)"
+#OCAML_LINK_FLAGS += -cclib "$(shell sdl-config --libs)"
+OCAML_LINK_FLAGS += -cclib "-L/usr/lib -lSDLmain -lSDL -mwindows"
 # OCAML_BYTE_LINK_FLAGS +=
 # OCAML_NATIVE_LINK_FLAGS +=

@@ -87,9 +88,14 @@ OCAML_LIBS += ../src/sdlcaml
 #
 .PHONY: clean

+# need sdlcaml library
+RequiredFiles(../src/sdlcaml$(EXT_LIB))
+
 .DEFAULT: $(OCamlProgram $(PROGRAM), $(FILES))

 clean:
+	rm -f $(PROGRAM)$(EXE)
+	rm -f $(PROGRAM).opt
 	rm -f *cmx
 	rm -f *cmo
 	rm -f *cmi
diff --git a/test/test_sdl_video.ml b/test/test_sdl_video.ml
index b6bd791..038002b 100644
--- a/test/test_sdl_video.ml
+++ b/test/test_sdl_video.ml
@@ -1,11 +1,11 @@
 open Sdlcaml
 open OUnit

-let test_set_up _ =
+let test_set_up flag _ =
   begin
     Sdl.sdl_init [`VIDEO];
-    Sdl_video.sdl_set_video_mode ~width:640 ~height:480 ~depth:24
-      ~flags:[Sdl_video.SDL_SWSURFACE];
+    Sdl_video.sdl_set_video_mode ~width:640 ~height:480 ~depth:32
+      ~flags:flag;
   end

 let test_tear_down surface =
@@ -16,15 +16,15 @@ let test_tear_down surface =

 let test_sdl_video_init surface =
   begin
-    Thread.delay 3.0;
+    Thread.delay 1.0;
   end

 let test_sdl_get_pixel_format surface =
   begin
     let format = Sdl_video.sdl_get_pixelformat surface in
     let open Sdl_video in
-    assert_equal 24 format.bits_per_pixel;
-    assert_equal 3 format.bytes_per_pixel;
+    assert_equal 32 format.bits_per_pixel;
+    assert_equal 4 format.bytes_per_pixel;
     assert_equal 0xFF0000 format.rmask;
     assert_equal 0xFF00 format.gmask;
     assert_equal 0xFF format.bmask;
@@ -34,8 +34,9 @@ let test_sdl_fill_color surface =
   begin
     let open Sdl_video in
     let col = {red = 255; green = 128; blue = 0; alpha = 255} in
-    Sdl_video.sdl_fill_color ~dist:surface ~fill:col ();
-    Thread.delay 5.0;
+    Sdl_video.sdl_fill_rect ~dist:surface ~fill:col ();
+    Sdl_video.sdl_update_rect surface;
+    Thread.delay 2.0;
   end

 let test_sdl_blit_surface surface =
@@ -44,21 +45,59 @@ let test_sdl_blit_surface surface =
     let newsurface = Sdl_video.sdl_create_surface
       ~flags:[SDL_SWSURFACE;SDL_SRCALPHA] ~width:300 ~height:200
     and col = {red = 255; green = 128; blue = 0; alpha = 255} in
-    Sdl_video.sdl_fill_color ~dist:newsurface ~fill:col ();
-    assert_equal BLIT_SUCCESS (Sdl_video.sdl_blit_surface ~src:newsurface ~dist:surface ());
-    Thread.delay 3.0;
+    Sdl_video.sdl_fill_rect ~dist:newsurface ~fill:col ();
+    assert_equal BLIT_SUCCESS (Sdl_video.sdl_blit_surface
+                                 ~src:newsurface ~dist:surface ());
+    Sdl_video.sdl_update_rect surface;
+    Thread.delay 2.0;
+    Sdl_video.sdl_free_surface newsurface;
+  end
+
+let test_use_alpha surface =
+  begin
+    let open Sdl_video in
+    let newsurface = Sdl_video.sdl_create_surface
+      ~flags:[SDL_SWSURFACE;SDL_SRCALPHA] ~width:300 ~height:200
+    and col = {red = 255; green = 128; blue = 0; alpha = 128} in
+    Sdl_video.sdl_fill_rect ~dist:newsurface ~fill:col ();
+    assert_equal BLIT_SUCCESS (Sdl_video.sdl_blit_surface
+                                 ~src:newsurface ~dist:surface ());
+    Sdl_video.sdl_update_rect surface;
+    Thread.delay 2.0;
+    Sdl_video.sdl_free_surface newsurface;
+  end
+
+let test_use_flip surface =
+  begin
+    let open Sdl_video in
+    let newsurface = Sdl_video.sdl_create_surface
+      ~flags:[SDL_SWSURFACE;SDL_SRCALPHA] ~width:300 ~height:200
+    and col = {red = 255; green = 128; blue = 0; alpha = 128} in
+    Sdl_video.sdl_fill_rect ~dist:newsurface ~fill:col ();
+    assert_equal BLIT_SUCCESS (Sdl_video.sdl_blit_surface
+                                 ~src:newsurface ~dist:surface ());
+    Sdl_video.sdl_flip surface;
+    Thread.delay 2.0;
     Sdl_video.sdl_free_surface newsurface;
   end

 let suite = "SDL video tests" >:::
-  [ "video initialize" >:: (bracket test_set_up test_sdl_video_init
-                               test_tear_down);
+  [ "video initialize" >::
+      (bracket (test_set_up [Sdl_video.SDL_SWSURFACE]) test_sdl_video_init
+         test_tear_down);
     "get current pixel format" >::
-      (bracket test_set_up test_sdl_get_pixel_format test_tear_down);
+      (bracket (test_set_up [Sdl_video.SDL_SWSURFACE]) test_sdl_get_pixel_format test_tear_down);
     "fill color" >::
-      (bracket test_set_up test_sdl_fill_color test_tear_down);
+      (bracket (test_set_up [Sdl_video.SDL_SWSURFACE]) test_sdl_fill_color test_tear_down);
     "blit surface" >::
-      (bracket test_set_up test_sdl_blit_surface test_tear_down);
+      (bracket (test_set_up [Sdl_video.SDL_SWSURFACE]) test_sdl_blit_surface test_tear_down);
+    "use alpha" >::
+      (bracket (test_set_up [Sdl_video.SDL_SWSURFACE]) test_use_alpha
+  test_tear_down);
+    "use double buffering" >::
+      (bracket (test_set_up
+                  [Sdl_video.SDL_SWSURFACE;Sdl_video.SDL_DOUBLEBUF])
+         test_use_flip test_tear_down);

   ]