diff --git a/src/frame.cpp b/src/frame.cpp
index 4416f58..84ccc7d 100644
--- a/src/frame.cpp
+++ b/src/frame.cpp
@@ -18,6 +18,7 @@ void Frame::RemoveChild(Frame* f) {
 }
 
 void Frame::Init(Frame* parent, const char* label, unsigned int flags) {
+  sBody = 0;
   m_parent = parent;
   m_flags = flags;
   m_radius = 0;
diff --git a/src/frame.h b/src/frame.h
index 555e65e..917890f 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -2,6 +2,7 @@
 #include <string>
 #include <list>
 #include "libs.h"
+#include "star_system.h"
 
 /* Frame of reference. */
 class Frame {
@@ -33,6 +34,7 @@ public:
   /* If parent is null then frame position is absolute. */
   Frame* m_parent;
   std::list<Frame*> m_children;
+  StarSystem::SBody* sBody; /* Points to SBodies in L3D::current_system. */
 
   enum { TEMP_VIEWING=1 };
 
diff --git a/src/l3d.h b/src/l3d.h
index 16da893..08acfc0 100644
--- a/src/l3d.h
+++ b/src/l3d.h
@@ -82,6 +82,7 @@ public:
   static InfoView*          infoView;
   static ShipCpanel*        cpan;
   static GLUquadric*        gluQuadric;
+  static StarSystem*        current_system;
 
 private:
   static void InitOpenGL(void);
diff --git a/src/main.cpp b/src/main.cpp
index 15fd495..050c9ed 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -44,6 +44,7 @@ SystemView*       L3D::system_view;
 SystemInfoView*   L3D::system_info_view;
 ShipCpanel*       L3D::cpan;
 StarSystem*       L3D::selected_system;
+StarSystem*       L3D::current_system;
 MTRand            L3D::rng;
 double            L3D::gameTime;
 float             L3D::frameTime;
@@ -309,8 +310,14 @@ StarSystem* L3D::GetSelectedSystem(void) {
 }
 
 void L3D::HyperspaceTo(StarSystem* dest) {
+  int sec_x, sec_y, sys_idx;
+  dest->GetPos(&sec_x, &sec_y, &sys_idx);
+
+  if(current_system) delete current_system;
+  current_system = new StarSystem(sec_x, sec_y, sys_idx);
+
   Space::Clear();
-  Space::BuildSystem(dest);
+  Space::BuildSystem();
   float ang = rng.Double(M_PI);
   L3D::player->SetPosition(vector3d(sin(ang)*8*AU, cos(ang)*8*AU, 0));
   dest->GetPos(&L3D::playerLoc);
diff --git a/src/player.cpp b/src/player.cpp
index 34c1d76..e222bd5 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -245,11 +245,11 @@ void Player::DrawHUD(const Frame* cam_frame) {
     vector3d abs_pos = GetPositionRelTo(Space::GetRootFrame());
     const char* rel_to = (GetFrame() ? GetFrame()->GetLabel() : "System");
     snprintf(buf, sizeof(buf), "Pos: %.1f,%.1f,%.1f\n"
-             "AbsPos: %.1f,%.1f,%.1f\n"
-             "Rel-to: %s",
+             "AbsPos: %.1f,%.1f,%.1f (%.3f AU)\n"
+             "Rel-to: %s (%.0f km)",
              pos.x, pos.y, pos.z,
-             abs_pos.x, abs_pos.y, abs_pos.z,
-             rel_to);
+             abs_pos.x, abs_pos.y, abs_pos.z, abs_pos.Length()/AU,
+             rel_to, pos.Length()/1000);
     Gui::Screen::RenderString(buf);
     glPopMatrix();
   }
diff --git a/src/space.cpp b/src/space.cpp
index 7eb219f..7ef4ff7 100644
--- a/src/space.cpp
+++ b/src/space.cpp
@@ -41,8 +41,22 @@ void Space::Clear(void) {
   L3D::player->SetFrame(rootFrame);
 }
 
-void Space::GenBody(StarSystem* system, StarSystem::SBody* sbody, Frame* f) {
+void Space::MoveFramesOfReference(Frame* f) {
+  if(f->sBody) {
+    vector3d pos = f->sBody->orbit.CartesianPosAtTime(L3D::GetGameTime());
+    f->SetPosition(pos);
+  }
+
+  for(std::list<Frame*>::iterator i = f->m_children.begin(); i != f->m_children.end(); ++i) {
+    MoveFramesOfReference(*i);
+  }
+}
+
+void Space::GenBody(StarSystem::SBody* sbody, Frame* f) {
   Body* b;
+
+  if(sbody->type == StarSystem::TYPE_GRAVPOINT) goto just_make_child;
+
   if(sbody->GetSuperType() == StarSystem::SUPERTYPE_STAR) {
     Star* star = new Star(sbody);
     b = star;
@@ -59,24 +73,27 @@ void Space::GenBody(StarSystem* system, StarSystem::SBody* sbody, Frame* f) {
     vector3d pos = sbody->orbit.CartesianPosAtTime(0);
     myframe->SetPosition(pos);
     myframe->SetRadius(10*sbody->GetRadius());
+    myframe->sBody = sbody;
     b->SetFrame(myframe);
   } else {
     b->SetFrame(f);
     myframe = f;
   }
+  f = myframe;
 
   b->SetPosition(vector3d(0, 0, 0));
 
   AddBody(b);
 
+just_make_child:
   for(std::vector<StarSystem::SBody*>::iterator i = sbody->children.begin();
       i != sbody->children.end(); ++i) {
-    GenBody(system, *i, myframe);
+    GenBody(*i, f);
   }
 }
 
-void Space::BuildSystem(StarSystem* system) {
-  GenBody(system, system->rootBody, rootFrame);
+void Space::BuildSystem(void) {
+  GenBody(L3D::current_system->rootBody, rootFrame);
 }
 
 void Space::AddBody(Body* b) {
@@ -223,6 +240,7 @@ void Space::TimeStep(float step) {
 
   /* TODO: Does not need to be done this often. */
   UpdateFramesOfReference();
+  MoveFramesOfReference(rootFrame);
 
   for(bodiesIter_t i = bodies.begin(); i != bodies.end(); ++i) {
     (*i)->TimeStepUpdate(step);
diff --git a/src/space.h b/src/space.h
index 725d592..08366e5 100644
--- a/src/space.h
+++ b/src/space.h
@@ -11,8 +11,8 @@ class Space {
 public:
   static void Init(void);
   static void Clear(void);
-  static void BuildSystem(StarSystem* s);
-  static void GenBody(StarSystem* s, StarSystem::SBody* b, Frame* f);
+  static void BuildSystem(void);
+  static void GenBody(StarSystem::SBody* b, Frame* f);
   static void TimeStep(float step);
   static void AddBody(Body*);
   static void KillBody(Body*);
@@ -24,6 +24,7 @@ public:
   typedef std::list<Body*>::iterator bodiesIter_t;
   static Frame* rootFrame;
 private:
+  static void MoveFramesOfReference(Frame* f);
   static void UpdateFramesOfReference(void);
   static void CollideFrame(Frame* f);
   static void PruneCorpses(void);
diff --git a/src/star_system.cpp b/src/star_system.cpp
index be087fb..c814a40 100644
--- a/src/star_system.cpp
+++ b/src/star_system.cpp
@@ -6,7 +6,8 @@
 #define DEBUG_DUMP
 
 /* Indexed by enum type. */
-float StarSystem::starColors[7][3] = {
+float StarSystem::starColors[][3] = {
+  { 0, 0, 0 },       /* Gravpoint. /
   { 1.0, 0.2, 0.0 }, /* M */
   { 1.0, 0.6, 0.1 }, /* K */
   { 1.0, 1.0, 0.4 }, /* G */
@@ -24,6 +25,9 @@ static const struct SBodySubTypeInfo {
   const char *icon;
   int tempMin, tempMax;
 } bodyTypeInfo[StarSystem::TYPE_MAX] = {
+  {
+    StarSystem::SUPERTYPE_NONE, 0, 0, "You can't see me!",
+  },
   {
     StarSystem::SUPERTYPE_STAR,
     40, 50, "Type 'M' red star",
@@ -387,14 +391,84 @@ StarSystem::StarSystem(int sector_x, int sector_y, int system_idx) {
   /* Primary. */
   SBody* primary = new SBody;
 
-  StarSystem::BodyType type = s.m_systems[system_idx].primaryStarClass;
-  primary->type         = type;
-  primary->parent       = NULL;
-  primary->radius       = fixed(bodyTypeInfo[type].radius, 100);
-  primary->mass         = fixed(bodyTypeInfo[type].mass, 100);
-  primary->averageTemp  = rand.Int32(bodyTypeInfo[type].tempMin,
-                                     bodyTypeInfo[type].tempMax);
-  rootBody = primary;
+  int isBinary = rand.Int32(2);
+  if(!isBinary) {
+    StarSystem::BodyType type = s.m_systems[system_idx].primaryStarClass;
+    primary->type = type;
+    primary->parent = NULL;
+    primary->radius = fixed(bodyTypeInfo[type].radius, 100);
+    primary->mass = fixed(bodyTypeInfo[type].mass, 100);
+    primary->averageTemp = rand.Int32(bodyTypeInfo[type].tempMin,
+                                      bodyTypeInfo[type].tempMax);
+    primary->name = s.m_systems[system_idx].name;
+    rootBody = primary;
+  } else {
+    SBody* centGrav = new SBody;
+    centGrav->type = TYPE_GRAVPOINT;
+    centGrav->parent = NULL;
+    centGrav->name = s.m_systems[system_idx].name;
+    rootBody = centGrav;
+
+    fixed ecc = rand.NFixed(3);
+    StarSystem::BodyType type = s.m_systems[system_idx].primaryStarClass;
+    SBody* star[2];
+    star[0] = new SBody;
+    star[0]->type = type;
+    star[0]->name = s.m_systems[system_idx].name+" A";
+    star[0]->parent = centGrav;
+    star[0]->radius = fixed(bodyTypeInfo[type].radius, 100);
+    star[0]->mass = fixed(bodyTypeInfo[type].mass, 100);
+    star[0]->averageTemp = rand.Int32(bodyTypeInfo[type].tempMin,
+                                      bodyTypeInfo[type].tempMax);
+
+    /*
+     * Usually, star types are chosen by spectral class distribution in
+     * our galactic neighbourhood. In binary systems, we instead just choose
+     * random companion types up to spectral class of primary.
+     */
+    StarSystem::BodyType type2 = (BodyType)rand.Int32(TYPE_STAR_M, type);
+    star[1] = new SBody;
+    star[1]->type = type2;
+    star[1]->name = s.m_systems[system_idx].name+" B";
+    star[1]->parent = centGrav;
+    star[1]->radius  = fixed(bodyTypeInfo[type2].radius, 100);
+    star[1]->mass = fixed(bodyTypeInfo[type2].mass, 100);
+    star[1]->averageTemp = rand.Int32(bodyTypeInfo[type2].tempMin,
+                                      bodyTypeInfo[type2].tempMax);
+    fixed m = star[0]->mass + star[1]->mass;
+    fixed a0 = star[1]->mass / m;
+    fixed a1 = star[0]->mass / m;
+    fixed semiMajorAxis;
+
+    switch(rand.Int32(3)) {
+      case 2: semiMajorAxis = fixed(rand.Int32(100, 10000), 100); break;
+      case 1: semiMajorAxis = fixed(rand.Int32(10, 1000), 100); break;
+      default:
+        case 0: semiMajorAxis = fixed(rand.Int32(1, 100), 100); break;
+    }
+    printf("Binary seperation: %.2fAU\n", semiMajorAxis.ToDouble());
+
+    star[0]->orbit.eccentricity = ecc.ToDouble();
+    star[0]->orbit.semiMajorAxis = AU * (semiMajorAxis*a0).ToDouble();
+    star[0]->orbit.period = 60*60*24*365*semiMajorAxis.ToDouble()*sqrt(semiMajorAxis.ToDouble() / m.ToDouble());
+    star[0]->orbit.rotMatrix = matrix4x4d::RotateZMatrix(M_PI);
+
+    star[1]->orbit.eccentricity = ecc.ToDouble();
+    star[1]->orbit.semiMajorAxis = AU * (semiMajorAxis*a1).ToDouble();
+    star[1]->orbit.period = star[0]->orbit.period;
+    star[1]->orbit.rotMatrix = matrix4x4d::Identity();
+
+    fixed radMin = semiMajorAxis - ecc*semiMajorAxis;
+    fixed radMax = 2*semiMajorAxis - radMin;
+    star[0]->radMin = radMin;
+    star[1]->radMin = radMin;
+    star[0]->radMax = radMax;
+    star[1]->radMax = radMax;
+
+    centGrav->children.push_back(star[0]);
+    centGrav->children.push_back(star[1]);
+    return;
+  }
 
   /* FIXME: Not good if the enum is tampered with... */
   int disc_size = rand.Int32(6, 100) + rand.Int32(60,140)*primary->type*primary->type;
diff --git a/src/star_system.h b/src/star_system.h
index f5c513d..2ac4cad 100644
--- a/src/star_system.h
+++ b/src/star_system.h
@@ -22,6 +22,7 @@ struct CustomSBody;
 /* Doubles: All masses are in Kg, all lengths in meters. */
 class StarSystem {
 public:
+  StarSystem(void) { rootBody = 0; }
   StarSystem(int sector_x, int sector_y, int system_idx);
   ~StarSystem(void);
   bool IsSystem(int sector_x, int sector_y, int system_idx);
@@ -30,7 +31,7 @@ public:
     *sec_x = loc.secX; *sec_y = loc.secY, *sys_idx = loc.sysIdx;
   }
 
-  static float starColors[7][3];
+  static float starColors[][3];
 
   struct Orbit {
     void KeplerPosAtTime(double t, double* dist, double* ang);
@@ -42,6 +43,7 @@ public:
   };
 
   enum BodyType {
+    TYPE_GRAVPOINT,
     TYPE_STAR_M,
     TYPE_STAR_K,
     TYPE_STAR_G,
diff --git a/src/system_info_view.cpp b/src/system_info_view.cpp
index 74a9806..5fd514a 100644
--- a/src/system_info_view.cpp
+++ b/src/system_info_view.cpp
@@ -53,23 +53,48 @@ void SystemInfoView::OnBodySelected(StarSystem::SBody* b) {
 void SystemInfoView::SystemChanged(StarSystem* s) {
   DeleteAllChildren();
   float csize[2];
+  int majorBodies = 0;
   GetSize(csize);
 
   float xpos = 0;
   float size[2];
-  Gui::ImageButton* ib = new Gui::ImageButton(s->rootBody->GetIcon());
-  ib->GetSize(size);
-  ib->onClick.connect(sigc::bind(sigc::mem_fun(this, &SystemInfoView::OnBodySelected), s->rootBody));
-  Add(ib, 0, csize[1] - size[1]);
-  xpos += size[0];
-  float ycent = csize[1] - size[1]*0.5;
+  float ycent;
+  std::vector<StarSystem::SBody*>::iterator i = s->rootBody->children.begin();
 
-  for(std::vector<StarSystem::SBody*>::iterator i = s->rootBody->children.begin();
-      i != s->rootBody->children.end(); ++i) {
+  if(s->rootBody->type == StarSystem::TYPE_GRAVPOINT) {
+    /* Binary system. */
+    Gui::ImageButton* ib = new Gui::ImageButton((*i)->GetIcon());
+    ib->GetSize(size);
+    ib->onClick.connect(sigc::bind(sigc::mem_fun(this, &SystemInfoView::OnBodySelected), *i));
+    Add(ib, 0, csize[1] - size[1]);
+    float yoffset = size[1];
+    float xoffset = size[0];
+    ++i; majorBodies++;
+
+    ib = new Gui::ImageButton((*i)->GetIcon());
+    ib->GetSize(size);
+    ib->onClick.connect(sigc::bind(sigc::mem_fun(this, &SystemInfoView::OnBodySelected), *i));
+    Add(ib, 0, csize[1] - size[1] - yoffset);
+    ++i; majorBodies++;
+
+    xpos += xoffset;
+    ycent = csize[1] - yoffset*0.5;
+  } else {
+    Gui::ImageButton* ib = new Gui::ImageButton(s->rootBody->GetIcon());
+    ib->GetSize(size);
+    ib->onClick.connect(sigc::bind(sigc::mem_fun(this, &SystemInfoView::OnBodySelected), s->rootBody));
+    Add(ib, 0, csize[1] - size[1]);
+    xpos += size[0];
+    ycent = csize[1] - size[1]*0.5;
+    majorBodies++;
+  }
+
+  for(; i != s->rootBody->children.end(); ++i) {
     Gui::ImageButton* ib = new Gui::ImageButton((*i)->GetIcon());
     ib->GetSize(size);
     ib->onClick.connect(sigc::bind(sigc::mem_fun(this, &SystemInfoView::OnBodySelected), *i));
     Add(ib, xpos, ycent - 0.5*size[1]);
+    majorBodies++;
 
     float moon_ypos = ycent - size[1] - 5;
     if((*i)->children.size())
@@ -86,7 +111,7 @@ void SystemInfoView::SystemChanged(StarSystem* s) {
   }
 
   char buf[512];
-  snprintf(buf, sizeof(buf), "Stable system with %d major bodies.", 1+s->rootBody->children.size());
+  snprintf(buf, sizeof(buf), "Stable system with %d major bodies", majorBodies);
   m_infoText = new Gui::Label(buf);
   m_infoText->SetColor(1, 1, 0);
   Add(m_infoText, 50, 200);
diff --git a/src/system_view.cpp b/src/system_view.cpp
index 6f28d2b..df59038 100644
--- a/src/system_view.cpp
+++ b/src/system_view.cpp
@@ -116,13 +116,15 @@ void SystemView::PutLabel(StarSystem::SBody* b) {
 #define ROUGH_SIZE_OF_THING 10.0
 
 void SystemView::PutBody(StarSystem::SBody* b) {
-  glPointSize(5);
-  glColor3f(1,1,1);
-  glBegin(GL_POINTS);
-  glVertex3f(0,0,0);
-  glEnd();
-
-  PutLabel(b);
+  if(b->type != StarSystem::TYPE_GRAVPOINT) {
+    glPointSize(5);
+    glColor3f(1,1,1);
+    glBegin(GL_POINTS);
+    glVertex3f(0,0,0);
+    glEnd();
+    
+    PutLabel(b);
+  }
 
   if(b->children.size())
     for(std::vector<StarSystem::SBody*>::iterator kid = b->children.begin(); 
diff --git a/src/world_view.cpp b/src/world_view.cpp
index 052d464..209aa8d 100644
--- a/src/world_view.cpp
+++ b/src/world_view.cpp
@@ -115,7 +115,7 @@ void WorldView::Draw3D(void) {
 }
 
 void WorldView::Update(void) {
-  if(L3D::GetSelectedSystem() /* && isn't current system */) {
+  if(L3D::GetSelectedSystem() && !L3D::player->GetDockedWith()/* && isn't current system */) {
     m_hyperspaceButton->Show();
   } else {
     m_hyperspaceButton->Hide();