diff --git a/game/engine/Entity.lua b/game/engine/Entity.lua
index 0de153a3424232df28e75b5f2bcc72e6c062bf4f..ca58f24206b4cfe0f286da705ae94c81211c95fa 100644
--- a/game/engine/Entity.lua
+++ b/game/engine/Entity.lua
@@ -135,9 +135,9 @@ function _M:loadList(...)
 				local e = self.new(t)
 				res[#res+1] = e
 				if t.define_as then res[t.define_as] = e end
-				print("new entity", t.name)
+--				print("new entity", t.name)
 				for k, ee in pairs(e) do
-					print("prop:", k, ee)
+--					print("prop:", k, ee)
 				end
 			end,
 			load = function(f)
diff --git a/game/engine/Map.lua b/game/engine/Map.lua
index 0c28e506ec9e2995a6ba6864873b83f7b00d0728..90aad086a93b07ce35e985da77294d95e9882ca3 100644
--- a/game/engine/Map.lua
+++ b/game/engine/Map.lua
@@ -32,7 +32,7 @@ rememberDisplayOrder = { ACTOR, TERRAIN }
 function _M:setViewPort(x, y, w, h, tile_w, tile_h, fontname, fontsize)
 	self.display_x, self.display_y = x, y
 	self.viewport = {width=w, height=h, mwidth=math.floor(w/tile_w), mheight=math.floor(h/tile_h)}
-	self.tiles = Tiles.new(tile_w, tile_h, fontname, fontsize)
+	self.tiles = Tiles.new(tile_w, tile_h, fontname, fontsize, true)
 	self.tile_w, self.tile_h = tile_w, tile_h
 end
 
@@ -57,6 +57,7 @@ function _M:init(w, h)
 	self.seens = {}
 	self.remembers = {}
 	self.effects = {}
+	self._map = core.map.newMap(w, h, self.mx, self.my, self.viewport.mwidth, self.viewport.mheight)
 	for i = 0, w * h - 1 do self.map[i] = {} end
 
 	self:loaded()
@@ -67,6 +68,7 @@ function _M:save()
 	return class.save(self, {
 		_fov_lite = true,
 		_fov = true,
+		_map = true,
 		surface = true
 	})
 end
@@ -75,6 +77,7 @@ function _M:loaded()
 		if x < 0 or y < 0 or x >= self.w or y >= self.h then return end
 		if v ~= nil then
 			t[x + y * self.w] = v
+			self:updateMap(x, y)
 		end
 		return t[x + y * self.w]
 	end
@@ -107,7 +110,10 @@ function _M:fov(x, y, d)
 	-- Reset seen grids
 	if self.clean_fov then
 		self.clean_fov = false
-		for i = 0, self.w * self.h - 1 do self.seens[i] = nil end
+		for i = 0, self.w - 1 do for j = 0, self.h - 1 do
+			self.seens(i, j, false)
+		end end
+--		for i = 0, self.w * self.h - 1 do self.seens[i] = nil end
 	end
 	self._fov(x, y, d)
 end
@@ -120,11 +126,32 @@ function _M:fovLite(x, y, d)
 	-- Reset seen grids
 	if self.clean_fov then
 		self.clean_fov = false
-		for i = 0, self.w * self.h - 1 do self.seens[i] = nil end
+		for i = 0, self.w - 1 do for j = 0, self.h - 1 do
+			self.seens(i, j, false)
+		end end
+--		for i = 0, self.w * self.h - 1 do self.seens[i] = nil end
 		self._fov_lite(x, y, d)
 	end
 end
 
+function _M:updateMap(x, y)
+	local order = displayOrder
+	local e, si = nil, 1
+	local z = x + y * self.w
+
+	if self.seens[z] or self.remembers[z] then
+		if not self.seens[z] then order = rememberDisplayOrder end
+		while not e and si <= #order do e = self(x, y, order[si]) si = si + 1 end
+		if e then
+			if self.seens[z] then
+				self._map:setGrid(x, y, self.tiles:get(e.display, e.color_r, e.color_g, e.color_b, e.color_br, e.color_bg, e.color_bb, e.image))
+			elseif self.remembers[z] then
+				self._map:setGrid(x, y, self.tiles:get(e.display, e.color_r/3, e.color_g/3, e.color_b/3, e.color_br/3, e.color_bg/3, e.color_bb/3, e.image))
+			end
+		end
+	end
+end
+
 --- Sets/gets a value from the map
 -- It is defined as the function metamethod, so one can simply do: mymap(x, y, Map.TERRAIN)
 -- @param x position
@@ -136,6 +163,8 @@ function _M:call(x, y, pos, entity)
 	if entity then
 		self.map[x + y * self.w][pos] = entity
 		self.changed = true
+
+		self:updateMap(x, y)
 	else
 		if self.map[x + y * self.w] then
 			if not pos then
@@ -154,6 +183,7 @@ end
 function _M:remove(x, y, pos)
 	if self.map[x + y * self.w] then
 		self.map[x + y * self.w][pos] = nil
+		self:updateMap(x, y)
 		self.changed = true
 	end
 end
@@ -161,13 +191,19 @@ end
 --- Displays the map on a surface
 -- @return a surface containing the drawn map
 function _M:display()
+	do
+	self._map:toScreen(self.display_x, self.display_y)
+	self.changed = false
+	return
+	end
+
 	-- If nothing changed, return the same surface as before
-	if not self.changed then return self.surface end
+--	if not self.changed then return self.surface end
 	self.changed = false
 	self.clean_fov = true
 
 	-- Erase and the display the map
-	self.surface:erase()
+--	self.surface:erase()
 	if not self.multi_display then
 		-- Version without multi display
 		local e, si
@@ -184,9 +220,9 @@ function _M:display()
 				while not e and si <= #order do e = self(i, j, order[si]) si = si + 1 end
 				if e then
 					if self.seens[z] then
-						self.surface:merge(self.tiles:get(e.display, e.color_r, e.color_g, e.color_b, e.color_br, e.color_bg, e.color_bb, e.image), (i - self.mx) * self.tile_w, (j - self.my) * self.tile_h)
+						self.tiles:get(e.display, e.color_r, e.color_g, e.color_b, e.color_br, e.color_bg, e.color_bb, e.image):toScreen((i - self.mx) * self.tile_w, (j - self.my) * self.tile_h)
 					elseif self.remembers[z] then
-						self.surface:merge(self.tiles:get(e.display, e.color_r/3, e.color_g/3, e.color_b/3, e.color_br/3, e.color_bg/3, e.color_bb/3, e.image), (i - self.mx) * self.tile_w, (j - self.my) * self.tile_h)
+						self.tiles:get(e.display, e.color_r/3, e.color_g/3, e.color_b/3, e.color_br/3, e.color_bg/3, e.color_bb/3, e.image):toScreen((i - self.mx) * self.tile_w, (j - self.my) * self.tile_h)
 					end
 					-- Tactical overlay ?
 					if self.view_faction and e.faction then
@@ -246,6 +282,7 @@ function _M:apply(x, y)
 	if self.lites[x + y * self.w] then
 		self.seens[x + y * self.w] = true
 		self.remembers[x + y * self.w] = true
+		self:updateMap(x, y)
 	end
 end
 
@@ -256,6 +293,7 @@ function _M:applyLite(x, y)
 	self.lites[x + y * self.w] = true
 	self.seens[x + y * self.w] = true
 	self.remembers[x + y * self.w] = true
+	self:updateMap(x, y)
 end
 
 --- Check all entities of the grid for a property
@@ -328,6 +366,7 @@ function _M:checkMapViewBounded()
 	if self.my < 0 then self.my = 0 self.changed = true end
 	if self.mx > self.w - self.viewport.mwidth then self.mx = self.w - self.viewport.mwidth self.changed = true end
 	if self.my > self.h - self.viewport.mheight then self.my = self.h - self.viewport.mheight self.changed = true end
+	self._map:setScroll(self.mx, self.my)
 end
 
 --- Gets the tile under the mouse
diff --git a/game/engine/Tiles.lua b/game/engine/Tiles.lua
index e0365a7d1997ac33f64e39ddfbd8f6d5cdd870e7..68bff87f9fa729293267f987735148cd3e56c520 100644
--- a/game/engine/Tiles.lua
+++ b/game/engine/Tiles.lua
@@ -7,7 +7,8 @@ module(..., package.seeall, class.make)
 prefix = "/data/gfx/"
 use_images = true
 
-function _M:init(w, h, fontname, fontsize)
+function _M:init(w, h, fontname, fontsize, texture)
+	self.texture = texture
 	self.w, self.h = w, h
 	self.font = core.display.newFont(fontname or "/data/font/VeraMono.ttf", fontsize or 14)
 	self.repo = {}
@@ -41,9 +42,12 @@ function _M:get(char, fr, fg, fb, br, bg, bb, image)
 			s:drawString(self.font, char, (self.w - w) / 2, (self.h - h) / 2, fr, fg, fb)
 		end
 
+		if self.texture then s = s:glTexture() end
+
 		self.repo[char] = self.repo[char] or {}
 		self.repo[char][fgidx] = self.repo[char][fgidx] or {}
 		self.repo[char][fgidx][bgidx] = s
+		print("caching")
 		return s
 	end
 end
diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua
index 2d65dcfb2d978307b85bd43cf9055a84fed4f76a..419e71094e1ff4d6d223ff5ddc7ad2fc2aee3ad0 100644
--- a/game/modules/tome/class/Game.lua
+++ b/game/modules/tome/class/Game.lua
@@ -74,7 +74,7 @@ function _M:newGame()
 	self.zone = Zone.new("ancient_ruins")
 	self.player = Player.new{
 		name=self.player_name, max_life=25, max_mana=25, max_stamina=25, display='@', color_r=230, color_g=230, color_b=230,
-		unused_stats = 6, unused_talents = 3,
+		unused_stats = 6, unused_talents = 3, image="player.png",
 		move_others=true,
 	}
 
@@ -144,6 +144,18 @@ function _M:onTurn()
 end
 
 function _M:display()
+--[[
+	if self.level and self.level.map then
+		-- Display the map and compute FOV for the player if needed
+--		if self.level.map.changed then
+--			self.level.map:fov(self.player.x, self.player.y, 20)
+--			self.level.map:fovLite(self.player.x, self.player.y, 4)
+--		end
+		self.level.map:display()
+		--:toScreen(self.level.map.display_x, self.level.map.display_y)
+	end
+-- ]]
+-- [[
 	self.log:display():toScreen(self.log.display_x, self.log.display_y)
 	self.player_display:display():toScreen(self.player_display.display_x, self.player_display.display_y)
 	self.talents_display:display():toScreen(self.talents_display.display_x, self.talents_display.display_y)
@@ -154,7 +166,8 @@ function _M:display()
 			self.level.map:fov(self.player.x, self.player.y, 20)
 			self.level.map:fovLite(self.player.x, self.player.y, 4)
 		end
-		self.level.map:display():toScreen(self.level.map.display_x, self.level.map.display_y)
+		self.level.map:display()
+--		:toScreen(self.level.map.display_x, self.level.map.display_y)
 
 		-- Display the targetting system if active
 		self.target:display()
@@ -179,6 +192,7 @@ function _M:display()
 	end
 
 	engine.GameTurnBased.display(self)
+-- ]]
 end
 
 function _M:targetMode(v, msg, co, typ)
diff --git a/game/modules/tome/data/zones/ancient_ruins/zone.lua b/game/modules/tome/data/zones/ancient_ruins/zone.lua
index 6635de37d206c009e55ed576125a22f46c478bf6..971dc8047d6f5ca407c6f313d49b533e63b9e9dd 100644
--- a/game/modules/tome/data/zones/ancient_ruins/zone.lua
+++ b/game/modules/tome/data/zones/ancient_ruins/zone.lua
@@ -2,7 +2,7 @@ return {
 	name = "ancient ruins",
 	level_range = {1, 5},
 	max_level = 5,
-	width = 50, height = 50,
+	width = 100, height = 100,
 --	all_remembered = true,
 	all_lited = true,
 --	persistant = true,
diff --git a/premake4.lua b/premake4.lua
index 15c1665c5bf43acdc19f7c89e9bce7afb4b4a13b..25bef7ef611435ac2fee7b7e8e99d206767ad884 100644
--- a/premake4.lua
+++ b/premake4.lua
@@ -42,7 +42,7 @@ configuration "macosx"
 	targetdir "."
 
 configuration "not macosx"
-	links { "SDL", "SDL_ttf", "SDL_image", "SDL_gfx", "SDL_mixer" }
+	links { "SDL", "SDL_ttf", "SDL_image", "SDL_gfx", "SDL_mixer", "GL", "GLU" }
 
 configuration "windows"
 	defines { [[TENGINE_HOME_PATH='"T-Engine"']] }
diff --git a/src/core_lua.c b/src/core_lua.c
index a5800481940442fe967ee2be94ecde9b306f59ba..98481dcee70c42c05ce038942fc3a43f902d6ec5 100644
--- a/src/core_lua.c
+++ b/src/core_lua.c
@@ -9,7 +9,6 @@
 #include "physfs.h"
 #include "SFMT.h"
 #include "mzip.h"
-#include <SDL.h>
 #include <SDL_ttf.h>
 
 /******************************************************************
@@ -390,15 +389,25 @@ static int sdl_new_surface(lua_State *L)
 	SDL_Surface **s = (SDL_Surface**)lua_newuserdata(L, sizeof(SDL_Surface*));
 	auxiliar_setclass(L, "sdl{surface}", -1);
 
+	Uint32 rmask, gmask, bmask, amask;
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+	rmask = 0xff000000;
+	gmask = 0x00ff0000;
+	bmask = 0x0000ff00;
+	amask = 0x000000ff;
+#else
+	rmask = 0x000000ff;
+	gmask = 0x0000ff00;
+	bmask = 0x00ff0000;
+	amask = 0xff000000;
+#endif
+
 	*s = SDL_CreateRGBSurface(
-		screen->flags,
+		SDL_SWSURFACE | SDL_SRCALPHA,
 		w,
 		h,
-		screen->format->BitsPerPixel,
-		screen->format->Rmask,
-		screen->format->Gmask,
-		screen->format->Bmask,
-		screen->format->Amask
+		32,
+		rmask, gmask, bmask, amask
 		);
 	return 1;
 }
@@ -453,13 +462,98 @@ static int sdl_surface_toscreen(lua_State *L)
 	SDL_Surface **s = (SDL_Surface**)auxiliar_checkclass(L, "sdl{surface}", 1);
 	int x = luaL_checknumber(L, 2);
 	int y = luaL_checknumber(L, 3);
+
+	/*
 	if (s && *s)
 	{
 		sdlDrawImage(screen, *s, x, y);
 	}
+	*/
+
+	GLuint t;
+	glGenTextures(1, &t);
+	glBindTexture(GL_TEXTURE_2D, t);
+
+	// Paramétrage de la texture.
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+	// get the number of channels in the SDL surface
+	GLint nOfColors = (*s)->format->BytesPerPixel;
+	GLenum texture_format;
+	if (nOfColors == 4)     // contains an alpha channel
+	{
+		if ((*s)->format->Rmask == 0x000000ff)
+			texture_format = GL_RGBA;
+		else
+			texture_format = GL_BGRA;
+	} else if (nOfColors == 3)     // no alpha channel
+	{
+		if ((*s)->format->Rmask == 0x000000ff)
+			texture_format = GL_RGB;
+		else
+			texture_format = GL_BGR;
+	} else {
+		printf("warning: the image is not truecolor..  this will probably break %d\n", nOfColors);
+		// this error should not go unhandled
+	}
+
+	// Jonction entre OpenGL et SDL.
+	glTexImage2D(GL_TEXTURE_2D, 0, 3, (*s)->w, (*s)->h, 0, texture_format, GL_UNSIGNED_BYTE, (*s)->pixels);
+
+	glBegin( GL_QUADS );                 /* Draw A Quad              */
+	glTexCoord2f(0,0); glVertex2f(0  + x, 0  + y);
+	glTexCoord2f(0,1); glVertex2f(0  + x, (*s)->h + y);
+	glTexCoord2f(1,1); glVertex2f((*s)->w + x, (*s)->h + y);
+	glTexCoord2f(1,0); glVertex2f((*s)->w + x, 0  + y);
+	glEnd( );                            /* Done Drawing The Quad    */
+
+	glDeleteTextures(1, &t);
+
 	return 0;
 }
 
+static int sdl_surface_to_texture(lua_State *L)
+{
+	SDL_Surface **s = (SDL_Surface**)auxiliar_checkclass(L, "sdl{surface}", 1);
+
+	GLuint *t = (GLuint*)lua_newuserdata(L, sizeof(GLuint));
+	auxiliar_setclass(L, "gl{texture}", -1);
+
+	glGenTextures(1, t);
+	glBindTexture(GL_TEXTURE_2D, *t);
+
+	// Paramétrage de la texture.
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+	// get the number of channels in the SDL surface
+	GLint nOfColors = (*s)->format->BytesPerPixel;
+	GLenum texture_format;
+	if (nOfColors == 4)     // contains an alpha channel
+	{
+		if ((*s)->format->Rmask == 0x000000ff)
+			texture_format = GL_RGBA;
+		else
+			texture_format = GL_BGRA;
+	} else if (nOfColors == 3)     // no alpha channel
+	{
+		if ((*s)->format->Rmask == 0x000000ff)
+			texture_format = GL_RGB;
+		else
+			texture_format = GL_BGR;
+	} else {
+		printf("warning: the image is not truecolor..  this will probably break\n");
+		// this error should not go unhandled
+	}
+
+	// Jonction entre OpenGL et SDL.
+	glTexImage2D(GL_TEXTURE_2D, 0, nOfColors, (*s)->w, (*s)->h, 0, texture_format, GL_UNSIGNED_BYTE, (*s)->pixels);
+	return 1;
+}
+
 static int sdl_surface_merge(lua_State *L)
 {
 	SDL_Surface **dst = (SDL_Surface**)auxiliar_checkclass(L, "sdl{surface}", 1);
@@ -488,6 +582,32 @@ static int sdl_set_window_title(lua_State *L)
 	return 0;
 }
 
+static int sdl_free_texture(lua_State *L)
+{
+	GLuint *t = (GLuint*)auxiliar_checkclass(L, "gl{texture}", 1);
+	glDeleteTextures(1, t);
+	lua_pushnumber(L, 1);
+	return 1;
+}
+
+static int sdl_texture_toscreen(lua_State *L)
+{
+	GLuint *t = (GLuint*)auxiliar_checkclass(L, "gl{texture}", 1);
+	int x = luaL_checknumber(L, 2);
+	int y = luaL_checknumber(L, 3);
+
+	glBindTexture(GL_TEXTURE_2D, *t);
+	glBegin( GL_QUADS );                 /* Draw A Quad              */
+	glTexCoord2f(0,0); glVertex2f(0  + x, 0  + y);
+	glTexCoord2f(0,1); glVertex2f(0  + x, 16 + y);
+	glTexCoord2f(1,1); glVertex2f(16 + x, 16 + y);
+	glTexCoord2f(1,0); glVertex2f(16 + x, 0  + y);
+	glEnd( );                            /* Done Drawing The Quad    */
+
+	return 0;
+}
+
+
 static const struct luaL_reg displaylib[] =
 {
 	{"fullscreen", sdl_fullscreen},
@@ -510,6 +630,15 @@ static const struct luaL_reg sdl_surface_reg[] =
 	{"putChar", lua_display_char},
 	{"drawString", sdl_surface_drawstring},
 	{"alpha", sdl_surface_alpha},
+	{"glTexture", sdl_surface_to_texture},
+	{NULL, NULL},
+};
+
+static const struct luaL_reg sdl_texture_reg[] =
+{
+	{"__gc", sdl_free_texture},
+	{"close", sdl_free_texture},
+	{"toScreen", sdl_texture_toscreen},
 	{NULL, NULL},
 };
 
@@ -1022,6 +1151,7 @@ int luaopen_core(lua_State *L)
 	auxiliar_newclass(L, "physfs{zip}", fszipfile_reg);
 	auxiliar_newclass(L, "line{core}", line_reg);
 	auxiliar_newclass(L, "fov{core}", fov_reg);
+	auxiliar_newclass(L, "gl{texture}", sdl_texture_reg);
 	auxiliar_newclass(L, "sdl{surface}", sdl_surface_reg);
 	auxiliar_newclass(L, "sdl{font}", sdl_font_reg);
 	luaL_openlib(L, "core.fov", fovlib, 0);
diff --git a/src/display_sdl.h b/src/display_sdl.h
index 2a3583e39bc58d92a1d938268e3f3e34c6beba8a..6a422e40897012b6c36f20cb84b5b865ba37590a 100644
--- a/src/display_sdl.h
+++ b/src/display_sdl.h
@@ -36,6 +36,8 @@
 
 #include <SDL.h>
 #include <SDL_framerate.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/src/main.c b/src/main.c
index 316f5522af010bc02a6cb1f63ca1f5979ee09784..f112105a1e5886147207da2988619b1a32fa101c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -13,6 +13,9 @@
 #include "physfs.h"
 #include "core_lua.h"
 
+#define WIDTH 800
+#define HEIGHT 600
+
 lua_State *L = NULL;
 int current_mousehandler = LUA_NOREF;
 int current_keyhandler = LUA_NOREF;
@@ -196,7 +199,7 @@ void on_tick()
 	Frames++;
 	{
 		int t = SDL_GetTicks();
-		if (t - T0 >= 5000) {
+		if (t - T0 >= 1000) {
 			float seconds = (t - T0) / 1000.0;
 			float fps = Frames / seconds;
 			printf("%d ticks  in %g seconds = %g TPS\n", Frames, seconds, fps);
@@ -211,8 +214,8 @@ void on_redraw()
 	static int Frames = 0;
 	static int T0     = 0;
 
-	sdlLock(screen);
-	SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0x00, 0x00, 0x00));
+	glClear( GL_COLOR_BUFFER_BIT);
+	glLoadIdentity();
 
 	if (current_game != LUA_NOREF)
 	{
@@ -224,16 +227,13 @@ void on_redraw()
 		docall(L, 1, 0);
 	}
 
-	sdlUnlock(screen);
-
-	// finally display the screen
-	SDL_Flip(screen);
+	SDL_GL_SwapBuffers();
 
 	/* Gather our frames per second */
 	Frames++;
 	{
 		int t = SDL_GetTicks();
-		if (t - T0 >= 5000) {
+		if (t - T0 >= 1000) {
 			float seconds = (t - T0) / 1000.0;
 			float fps = Frames / seconds;
 			printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);
@@ -287,6 +287,72 @@ Uint32 redraw_timer(Uint32 interval, void *param)
 	return(interval);
 }
 
+/* general OpenGL initialization function */
+int initGL()
+{
+	/* Enable smooth shading */
+//	glShadeModel( GL_SMOOTH );
+
+	/* Set the background black */
+	glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
+
+	/* Depth buffer setup */
+//	glClearDepth( 1.0f );
+
+	/* Enables Depth Testing */
+//	glEnable( GL_DEPTH_TEST );
+
+	/* The Type Of Depth Test To Do */
+//	glDepthFunc( GL_LEQUAL );
+
+	/* Really Nice Perspective Calculations */
+	//	glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
+
+	glEnable(GL_BLEND);
+	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+//	glDisable(GL_DEPTH_TEST);
+	glColor4f(1.0f,1.0f,1.0f,1.0f);
+//	glAlphaFunc(GL_GREATER,0.1f);
+
+	return( TRUE );
+}
+
+int resizeWindow(int width, int height)
+{
+	/* Height / width ration */
+	GLfloat ratio;
+
+	/* Protect against a divide by zero */
+	if ( height == 0 )
+		height = 1;
+
+	ratio = ( GLfloat )width / ( GLfloat )height;
+
+	glEnable( GL_TEXTURE_2D );
+
+	/* Setup our viewport. */
+	glViewport( 0, 0, ( GLsizei )width, ( GLsizei )height );
+
+	/* change to the projection matrix and set our viewing volume. */
+	glMatrixMode(GL_PROJECTION);
+	glLoadIdentity();
+
+	/* Set our perspective */
+	//gluPerspective( 45.0f, ratio, 0.1f, 100.0f );
+	glOrtho(0, width, height, 0, -100, 100);
+
+	/* Make sure we're chaning the model view and not the projection */
+	glMatrixMode( GL_MODELVIEW );
+
+	/* Reset The View */
+	glLoadIdentity( );
+
+//	glEnable(GL_ALPHA_TEST);
+//	glColor4f(1.0f,1.0f,1.0f,1.0f);
+
+	return( TRUE );
+}
+
 /**
  * Program entry point.
  */
@@ -308,7 +374,7 @@ int main(int argc, char *argv[])
 	luaopen_mime_core(L);
 	luaopen_struct(L);
 	luaopen_profiler(L);
-//	luaopen_map(L);
+	luaopen_map(L);
 
 	// Make the uids repository
 	lua_newtable(L);
@@ -320,7 +386,7 @@ int main(int argc, char *argv[])
 		printf("cannot initialize SDL: %s\n", SDL_GetError ());
 		return;
 	}
-	screen = SDL_SetVideoMode(800, 600, 32, _DEFAULT_VIDEOMODE_FLAGS_);
+	screen = SDL_SetVideoMode(WIDTH, HEIGHT, 32, SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE | SDL_HWSURFACE);
 	if (screen==NULL) {
 		printf("error opening screen: %s\n", SDL_GetError());
 		return;
@@ -330,6 +396,11 @@ int main(int argc, char *argv[])
 	SDL_EnableKeyRepeat(300, 10);
 	TTF_Init();
 
+	/* Sets up OpenGL double buffering */
+	SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+	initGL();
+	resizeWindow(WIDTH, HEIGHT);
+
 	// And run the lua engine scripts
 	luaL_loadfile(L, "/engine/init.lua");
 	docall(L, 0, 0);
@@ -371,6 +442,8 @@ int main(int argc, char *argv[])
 
 		/* draw the scene */
 		on_tick();
+//		on_redraw();
+
 	}
 
 	return 0;
diff --git a/src/map.c b/src/map.c
new file mode 100644
index 0000000000000000000000000000000000000000..93c2bb98714fd0de3200e9a38ea28f5aa08eab3e
--- /dev/null
+++ b/src/map.c
@@ -0,0 +1,137 @@
+#include "lua.h"
+#include "lauxlib.h"
+#include "lualib.h"
+#include "auxiliar.h"
+#include "types.h"
+#include "map.h"
+#include "script.h"
+#include <SDL.h>
+#include <SDL_ttf.h>
+
+static int map_new(lua_State *L)
+{
+	int w = luaL_checknumber(L, 1);
+	int h = luaL_checknumber(L, 2);
+	int mx = luaL_checknumber(L, 3);
+	int my = luaL_checknumber(L, 4);
+	int mwidth = luaL_checknumber(L, 5);
+	int mheight = luaL_checknumber(L, 6);
+
+	map_type *map = (map_type*)lua_newuserdata(L, sizeof(map_type));
+	auxiliar_setclass(L, "core{map}", -1);
+
+	map->w = w;
+	map->h = h;
+	map->mx = mx;
+	map->my = my;
+	map->mwidth = mwidth;
+	map->mheight = mheight;
+	map->grids = calloc(w, sizeof(GLuint*));
+	printf("size %d:%d :: %d\n", mwidth, mheight,mwidth * mheight);
+
+	int i;
+	for (i = 0; i < w; i++)
+	{
+		map->grids[i] = calloc(h, sizeof(GLuint));
+	}
+
+	map->dlist = glGenLists(1);
+
+	/* New compiled box display list */
+	glNewList(map->dlist, GL_COMPILE);
+		glBegin(GL_QUADS);
+		glTexCoord2f(0,0); glVertex2f(0  , 0  );
+		glTexCoord2f(0,1); glVertex2f(0  , 16 );
+		glTexCoord2f(1,1); glVertex2f(16 , 16 );
+		glTexCoord2f(1,0); glVertex2f(16 , 0  );
+		glEnd();
+	glEndList( );
+
+	return 1;
+}
+
+static int map_free(lua_State *L)
+{
+	map_type *map = (map_type*)auxiliar_checkclass(L, "core{map}", 1);
+	int i;
+
+	for (i = 0; i < map->w; i++)
+	{
+		free(map->grids[i]);
+	}
+	free(map->grids);
+
+	lua_pushnumber(L, 1);
+	return 1;
+}
+
+static int map_set_grid(lua_State *L)
+{
+	map_type *map = (map_type*)auxiliar_checkclass(L, "core{map}", 1);
+	int x = luaL_checknumber(L, 2);
+	int y = luaL_checknumber(L, 3);
+	GLuint *t = (GLuint*)auxiliar_checkclass(L, "gl{texture}", 4);
+
+	map->grids[x][y] = *t;
+}
+
+static int map_set_scroll(lua_State *L)
+{
+	map_type *map = (map_type*)auxiliar_checkclass(L, "core{map}", 1);
+	int x = luaL_checknumber(L, 2);
+	int y = luaL_checknumber(L, 3);
+
+	map->mx = x;
+	map->my = y;
+}
+
+static int map_to_screen(lua_State *L)
+{
+	map_type *map = (map_type*)auxiliar_checkclass(L, "core{map}", 1);
+	int x = luaL_checknumber(L, 2);
+	int y = luaL_checknumber(L, 3);
+	int i = 0, j = 0;
+
+	for (i = map->mx; i < map->mx + map->mwidth; i++)
+	{
+		for (j = map->my; j < map->my + map->mheight; j++)
+		{
+			if ((i >= map->w) || (j >= map->h) || (!map->grids[i][j])) continue;
+
+			int dx = x + (i - map->mx) * 16;
+			int dy = y + (j - map->my) * 16;
+
+			glBindTexture(GL_TEXTURE_2D, map->grids[i][j]);
+			glBegin(GL_QUADS);
+			glTexCoord2f(0,0); glVertex3f(0  +dx, 0  +dy,-99);
+			glTexCoord2f(1,0); glVertex3f(16 +dx, 0  +dy,-99);
+			glTexCoord2f(1,1); glVertex3f(16 +dx, 16 +dy,-99);
+			glTexCoord2f(0,1); glVertex3f(0  +dx, 16 +dy,-99);
+			glEnd();
+		}
+	}
+}
+
+static const struct luaL_reg maplib[] =
+{
+	{"newMap", map_new},
+	{NULL, NULL},
+};
+
+static const struct luaL_reg map_reg[] =
+{
+	{"__gc", map_free},
+	{"close", map_free},
+	{"setGrid", map_set_grid},
+	{"setScroll", map_set_scroll},
+	{"toScreen", map_to_screen},
+	{NULL, NULL},
+};
+
+int luaopen_map(lua_State *L)
+{
+	auxiliar_newclass(L, "core{map}", map_reg);
+//	auxiliar_newclass(L, "core{level}", level_reg);
+	luaL_openlib(L, "core.map", maplib, 0);
+	return 1;
+}
diff --git a/src/map.h b/src/map.h
new file mode 100644
index 0000000000000000000000000000000000000000..6f319d08f98b08630af01a3d614ff285c28e83f1
--- /dev/null
+++ b/src/map.h
@@ -0,0 +1,19 @@
+#ifndef _MAP_H_
+#define _MAP_H_
+
+#include <GL/gl.h>
+
+typedef struct {
+	GLuint **grids;
+
+	GLuint dlist;
+
+	// Map size
+	int w;
+	int h;
+
+	// Scrolling
+	int mx, my, mwidth, mheight;
+} map_type;
+
+#endif