diff --git a/.gitignore b/.gitignore
index 7093131..01f424f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,5 +28,5 @@
 *bin/data
 *pack
 *core
-
+*screenshot.png
 
diff --git a/dat/start.xml b/dat/start.xml
index af6b2c2..d17a8d9 100644
--- a/dat/start.xml
+++ b/dat/start.xml
@@ -1,4 +1,5 @@
 <Start>
+  <name>Dark Tides</name>
   <player>
     <ship>Lancer</ship>
     <credits>
diff --git a/src/main.c b/src/main.c
index b7ef1a0..7b2a732 100644
--- a/src/main.c
+++ b/src/main.c
@@ -21,8 +21,12 @@
 #include "pack.h"
 #include "weapon.h"
 #include "faction.h"
+#include "xml.h"
 #include "pilot.h"
 
+#define XML_START_ID    "Start"
+#define START_DATA      "../dat/start.xml"
+
 #define CONF_FILE       "conf"
 #define MINIMUM_FPS     0.5
 
@@ -34,8 +38,10 @@ static int quit = 0; // Primary loop.
 static unsigned int time = 0; // Calculate FPS and movement.
 
 // Just some default crap.
-#define DATA_DEF  "data"
+#define DATA_DEF  "data" // Default data pack file.
+#define DATA_NAME_LEN 25  // Max length of data name.
 char* data = NULL;
+char dataname[DATA_NAME_LEN];
 static int show_fps = 1; // Default - True.
 static int max_fps = 0;
 
@@ -43,6 +49,8 @@ static int max_fps = 0;
 
 static void print_usage(char** argv);
 static void display_fps(const double dt);
+static void window_caption(void);
+static void data_name(void);
 // Update.
 static void update_all(void);
 
@@ -188,13 +196,26 @@ int main(int argc, char** argv) {
         namjoystick = strdup(optarg);
         break;
       case 'v':
-        LOG("Lephisto: version %d.%d.%d\n", VMAJOR, VMINOR, VREV);
+        LOG(APPNAME": version %d.%d.%d", VMAJOR, VMINOR, VREV);
       case 'h':
         print_usage(argv);
         exit(EXIT_SUCCESS);
     }
   }
+  
+  // Check if the data file is valid.
+  if(pack_check(data)) {
+    ERR("Data file '%s'not found", data);
+    WARN("You should specify which data file to use with '-d'");
+    WARN("See -h or --help for more information.");
+    SDL_Quit();
+    exit(EXIT_FAILURE);
+  }
 
+  data_name(); // Loads the data's name and friends.
+  LOG(" %s", dataname);
+  DEBUG();
+  
   // Random numbers.
   rng_init();
 
@@ -214,11 +235,10 @@ int main(int argc, char** argv) {
     exit(EXIT_FAILURE);
   }
 
-  // Window.
-  SDL_WM_SetCaption(APPNAME, NULL);
+  window_caption();
 
   // Input.
-  if(indjoystick >= 0 || namjoystick != NULL) {
+  if((indjoystick >= 0) || (namjoystick != NULL)) {
     if(joystick_init())
       WARN("Error initializing joystick input");
     if(namjoystick != NULL) {
@@ -307,7 +327,7 @@ int main(int argc, char** argv) {
 // ========================================================
 static double fps_dt = 1.;
 static void update_all(void) {
-  // dt in us.
+  // dt in ms/1000.
   double dt = (double)(SDL_GetTicks() - time) / 1000.;
   time = SDL_GetTicks();
   
@@ -319,7 +339,7 @@ static void update_all(void) {
     return;
   }
   // If FPS is limited.
-  else if(max_fps != 0 && dt < 1./max_fps) {
+  else if((max_fps != 0) && (dt < 1./max_fps)) {
     double delay = 1./max_fps - dt;
     SDL_Delay(delay);
     fps_dt += delay; // Make sure it displays the propper FPS.
@@ -351,6 +371,7 @@ static void display_fps(const double dt) {
   fps_dt += dt;
   fps_cur += 1.;
   if(fps_dt > 1.) {
+    // Recalculate every second.
     fps = fps_cur / fps_dt;
     fps_dt = fps_cur = 0.;
   }
@@ -360,3 +381,38 @@ static void display_fps(const double dt) {
     gl_print(NULL, &pos, NULL, "%3.2f", fps);
 }
 
+static void data_name(void) {
+  uint32_t bufsize;
+  char* buf = pack_readfile(DATA, START_DATA, &bufsize);
+
+  xmlNodePtr node;
+  xmlDocPtr doc = xmlParseMemory(buf, bufsize);
+
+  node = doc->xmlChildrenNode;
+  if(!xml_isNode(node, XML_START_ID)) {
+    ERR("Maformed '"START_DATA"' file: missing root element '"XML_START_ID"'");
+    return;
+  }
+
+  node = node->xmlChildrenNode; // First node.
+  if(node == NULL) {
+    ERR("Malformed '"START_DATA"' file: does not contain elements");
+    return;
+  }
+  do {
+    if(xml_isNode(node, "name"))
+      strncpy(dataname, xml_get(node), DATA_NAME_LEN);
+  } while((node = node->next));
+
+  xmlFreeDoc(doc);
+  free(buf);
+  xmlCleanupParser();
+}
+
+static void window_caption(void) {
+  char tmp[DATA_NAME_LEN+10];
+
+  snprintf(tmp, DATA_NAME_LEN+10, APPNAME" - %s", dataname);
+  SDL_WM_SetCaption(tmp, NULL);
+}
+
diff --git a/src/opengl.c b/src/opengl.c
index 285d8de..0a3f597 100644
--- a/src/opengl.c
+++ b/src/opengl.c
@@ -1,5 +1,6 @@
 #include <SDL.h>
 #include <SDL_image.h>
+#include <png.h>
 #include <ft2build.h>
 #include <freetype/freetype.h>
 #include <freetype/ftglyph.h>
@@ -43,6 +44,8 @@ static int pot(int n);
 static GLuint gl_loadSurface(SDL_Surface* surface, int* rw, int* rh);
 // Gl font.
 static void gl_fontMakeDList(FT_Face face, char ch, GLuint list_base, GLuint* tex_base, int* width_base);
+// PNG.
+int write_png(const char* file_name, png_bytep* rows, int w, int h, int colortype, int bitdepth);
 
 // ================
 // MISC!
@@ -133,6 +136,19 @@ static uint8_t* SDL_MapTrans(SDL_Surface* s) {
   return t;
 }
 
+// Take a screenshot.
+void gl_screenshot(const char* filename) {
+  SDL_Surface* screen = SDL_GetVideoSurface();
+  unsigned rowbytes = screen->w * 4;
+  unsigned char screenbuf[screen->h][rowbytes], *rows[screen->h];
+  int i;
+
+  glReadPixels(0, 0, screen->w, screen->h, GL_RGBA, GL_UNSIGNED_BYTE, screenbuf);
+
+  for(i = 0; i < screen->h; i++) rows[i] = screenbuf[screen->h - i - 1];
+  write_png(filename, rows, screen->w, screen->h, PNG_COLOR_TYPE_RGBA, 8);
+}
+
 // ================
 // TEXTURE!
 // ================
@@ -708,3 +724,43 @@ void gl_exit(void) {
   SDL_Quit();
 }
 
+// Saves a png.
+int write_png(const char* file_name, png_bytep* rows, int w, int h, int colortype, int bitdepth) {
+  png_structp png_ptr;
+  png_infop info_ptr;
+  FILE* fp = NULL;
+  char* doing = "Open for writing";
+
+  if(!(fp = fopen(file_name, "wb"))) goto fail;
+
+  doing = "Create png write struct";
+  if(!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) goto fail;
+
+  doing = "Create png info struct";
+  if(!(info_ptr = png_create_info_struct(png_ptr))) goto fail;
+  if(setjmp(png_jmpbuf(png_ptr))) goto fail;
+
+  doing = "Init IO";
+  png_init_io(png_ptr, fp);
+  png_set_IHDR(png_ptr, info_ptr, w, h, bitdepth, colortype, PNG_INTERLACE_NONE,
+        PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+  
+  doing = "Write info";
+  png_write_info(png_ptr, info_ptr);
+
+  doing = "Write image";
+  png_write_image(png_ptr, rows);
+
+  doing = "Write end";
+  png_write_end(png_ptr, NULL);
+
+  doing = "Closing file";
+  if(0 != fclose(fp)) goto fail;
+
+  return 0;
+
+fail:
+  WARN("write_png: Could not %s", doing);
+  return -1;
+}
+
diff --git a/src/opengl.h b/src/opengl.h
index c234eb0..35ab829 100644
--- a/src/opengl.h
+++ b/src/opengl.h
@@ -83,4 +83,5 @@ void gl_exit(void);
 // Misc.
 int gl_isTrans(const gl_texture* t, const int x, const int y);
 void gl_getSpriteFromDir(int* x, int* y, const gl_texture* t, const double dir);
+void gl_screenshot(const char* filename);
 
diff --git a/src/player.c b/src/player.c
index 69cfd12..0b0ab63 100644
--- a/src/player.c
+++ b/src/player.c
@@ -20,7 +20,7 @@
 
 #define START_DATA    "../dat/start.xml"
 
-#define POW2(x) ((x)*(x))
+#define pow2(x) ((x)*(x))
 
 #define GFX_GUI_FRAME        "../gfx/gui/frame.png"
 #define GFX_GUI_TARG_PILOT   "../gfx/gui/pilot.png"
@@ -38,8 +38,9 @@ typedef struct {
 } Keybind;
 static Keybind** player_input; // Contains the players keybindings.
 // Name of each keybinding.
-const char* keybindNames[] = { "accel", "left", "right", "primary", "target",
-      "target_nearest", "mapzoomin", "mapzoomout", "end" }; // Need to terminate in "end".
+const char* keybindNames[] = { "accel", "left", "right", // Movement.
+                              "primary", "target", "target_nearest", "board", // Combat.
+                              "mapzoomin", "mapzoomout", "screenshot", "end" }; // Misc.
 
 // Player stuff.
 Pilot* player = NULL; // extern in pilot.h
@@ -138,6 +139,9 @@ static int gui_parse(const xmlNodePtr parent, const char* name);
 static void gui_renderPilot(const Pilot* p);
 static void gui_renderBar(const glColor* c, const Vec2* p, const Rect* r, const double w);
 
+static void player_board(void);
+static void player_screenshot(void);
+
 // Create a new player.
 void player_new(void) {
   Ship* ship;
@@ -529,28 +533,28 @@ static void rect_parse(const xmlNodePtr parent, double* x, double* y, double* w,
   do {
     if(xml_isNode(cur, "x")) {
       if(x != NULL) {
-        *x = (double)atoi((char*)cur->children->content);
+        *x = xml_getFloat(cur);
         param |= (1<<0);
       } else
         WARN("Extra parameter 'x' found for GUI node '%s'", parent->name);
     }
     else if(xml_isNode(cur, "y")) {
       if(y != NULL) {
-        *y = (double)atoi((char*)cur->children->content);
+        *y = xml_getFloat(cur);
         param |= (1<<1);
       } else
         WARN("Extra parameter 'y' found for GUI node '%s'", parent->name);
     }
     else if(xml_isNode(cur, "w")) {
       if(w != NULL) {
-        *w = (double)atoi((char*)cur->children->content);
+        *w = xml_getFloat(cur);
         param |= (1<<2);
       } else
         WARN("Extra parameter 'w' found for GUI node '%s'", parent->name);
     }
     else if(xml_isNode(cur, "h")) {
       if(h != NULL) {
-        *h = (double)atoi((char*)cur->children->content);
+        *h = xml_getFloat(cur);
         param |= (1<<3);
       } else
         WARN("Extra parameter 'h' found for GUI node '%s'", parent->name);
@@ -736,6 +740,40 @@ void player_think(Pilot* player) {
   vect_pset(&player->solid->force, player->ship->thrust * player_acc, player->solid->dir);
 }
 
+void player_board(void) {
+  Pilot* p;
+
+  if(player_target == PLAYER_ID) {
+    player_message("You need a target to board first!");
+    return;
+  }
+  p = pilot_get(player_target);
+
+  if(!pilot_isFlag(p, PILOT_DISABLED)) {
+    player_message("You cannot board a ship that isn't disabled!");
+    return;
+  }
+  if(vect_dist(&player->solid->pos, &p->solid->pos) > p->ship->gfx_space->sw * PILOT_SIZE_APROX) {
+    player_message("You are too far away to board your target");
+    return;
+  }
+  if((pow2(VX(player->solid->vel)-VX(p->solid->vel)) + 
+        pow2(VY(player->solid->vel)-VY(p->solid->vel))) > (double)pow2(MAX_HYPERSPACE_VEL)) {
+    
+    player_message("You are going too fact to board the ship");
+    return;
+  }
+  player_message("Ship boarding isn't implemented yet! HAHA");
+}
+
+// Take a screenshot.
+static void player_screenshot(void) {
+  char filename[20];
+  // TODO not overwirte old screenshots.
+  strncpy(filename, "screenshot.png", 20);
+  gl_screenshot(filename);
+}
+
 // ================
 // INPUT!
 // ================
@@ -748,8 +786,10 @@ void input_setDefault(void) {
   input_setKeybind("primary",        KEYBIND_KEYBOARD, SDLK_SPACE, 0);
   input_setKeybind("target",         KEYBIND_KEYBOARD, SDLK_TAB,   0);
   input_setKeybind("target_nearest", KEYBIND_KEYBOARD, SDLK_r,     0);
+  input_setKeybind("board",          KEYBIND_KEYBOARD, SDLK_b,     0);
   input_setKeybind("mapzoomin",      KEYBIND_KEYBOARD, SDLK_UP,    0);
   input_setKeybind("mapzoomout",     KEYBIND_KEYBOARD, SDLK_DOWN,  0);
+  input_setKeybind("screenshot",     KEYBIND_KEYBOARD, SDLK_F12,   0);
 }
 
 // Initialization/exit functions (does not assign keys).
@@ -820,6 +860,10 @@ static void input_key(int keynum, double value, int abs) {
   else if(strcmp(player_input[keynum]->name, "target_nearest")==0) {
     if(value == KEY_PRESS) player_target = pilot_getHostile();
   }
+  // Board those ships.
+  else if(strcmp(player_input[keynum]->name, "board")==0) {
+    if(value == KEY_PRESS) player_board();
+  }
   // Zoom in.
   else if(strcmp(player_input[keynum]->name, "mapzoomin")==0) {
     if(value == KEY_PRESS && gui.radar.res < RADAR_RES_MAX)
@@ -830,6 +874,9 @@ static void input_key(int keynum, double value, int abs) {
     if(value == KEY_PRESS && gui.radar.res > RADAR_RES_MIN)
       gui.radar.res -= RADAR_RES_INTERVAL;
   }
+  else if(strcmp(player_input[keynum]->name, "screenshot")==0) {
+    if(value == KEY_PRESS) player_screenshot();
+  }
 
   //Make sure values are sane.
   player_acc = ABS(player_acc);
diff --git a/src/space.h b/src/space.h
index c1d2b12..f7d2d89 100644
--- a/src/space.h
+++ b/src/space.h
@@ -4,7 +4,7 @@
 #include "pilot.h"
 
 #define MIN_HYPERSPACE_DIST 1500
-#define MAX_HYPERSPACE_VEL  3
+#define MAX_HYPERSPACE_VEL  10
 
 // Planet types. I didn't take them from Star Trek, I promise.
 typedef enum {