diff --git a/icons/object_white_dwarf.png b/icons/object_white_dwarf.png
new file mode 100644
index 0000000..248828d
Binary files /dev/null and b/icons/object_white_dwarf.png differ
diff --git a/screenshot/atmos.png b/screenshot/atmos.png
new file mode 100644
index 0000000..2065a0c
Binary files /dev/null and b/screenshot/atmos.png differ
diff --git a/screenshot/labels.png b/screenshot/labels.png
new file mode 100644
index 0000000..c3a1e72
Binary files /dev/null and b/screenshot/labels.png differ
diff --git a/screenshot/launch.png b/screenshot/launch.png
new file mode 100644
index 0000000..442cf24
Binary files /dev/null and b/screenshot/launch.png differ
diff --git a/screenshot/ship_view.png b/screenshot/ship_view.png
new file mode 100644
index 0000000..3a95891
Binary files /dev/null and b/screenshot/ship_view.png differ
diff --git a/screenshot/sys_view.png b/screenshot/sys_view.png
new file mode 100644
index 0000000..cbaad42
Binary files /dev/null and b/screenshot/sys_view.png differ
diff --git a/screenshot/systems.png b/screenshot/systems.png
new file mode 100644
index 0000000..fadc1b8
Binary files /dev/null and b/screenshot/systems.png differ
diff --git a/screenshot/this_is_earth.png b/screenshot/this_is_earth.png
new file mode 100644
index 0000000..58bec56
Binary files /dev/null and b/screenshot/this_is_earth.png differ
diff --git a/src/sector.cpp b/src/sector.cpp
index b6fe706..206a5b3 100644
--- a/src/sector.cpp
+++ b/src/sector.cpp
@@ -49,9 +49,9 @@ Sector::Sector(int x, int y) {
 
       float spec = rng.Int32(1000000);
       /* Frequencies from wiki. :D */
-      if(spec < 1) {
+      /*if(spec < 1) {
         s.primaryStarClass = StarSystem::TYPE_STAR_O;
-      } else if(spec < 1300) {
+      } else*/ if(spec < 1300) {
         s.primaryStarClass = StarSystem::TYPE_STAR_B;
       } else if(spec < 7300) {
         s.primaryStarClass = StarSystem::TYPE_STAR_A;
@@ -61,6 +61,8 @@ Sector::Sector(int x, int y) {
         s.primaryStarClass = StarSystem::TYPE_STAR_G;
       } else if(spec < 234300) {
         s.primaryStarClass = StarSystem::TYPE_STAR_K;
+      } else if(spec < 250000) {
+        s.primaryStarClass = StarSystem::TYPE_WHITE_DWARF;
       } else {
         s.primaryStarClass = StarSystem::TYPE_STAR_M;
       }
diff --git a/src/star_system.cpp b/src/star_system.cpp
index c2545f9..99c2df8 100644
--- a/src/star_system.cpp
+++ b/src/star_system.cpp
@@ -7,142 +7,143 @@
 
 /* Indexed by enum type. */
 float StarSystem::starColors[][3] = {
-  { 0, 0, 0 },       /* Gravpoint. /
+  { 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 */
   { 1.0, 1.0, 0.8 }, /* F */
   { 1.0, 1.0, 1.0 }, /* A */
   { 0.7, 0.7, 1.0 }, /* B */
-  { 1.0, 0.7, 1.0 }  /* O */
+  { 1.0, 0.7, 1.0 }, /* O */
+  { 0.4, 0.4, 0.8 }  /* White dwarf. */
 };
 
 static const struct SBodySubTypeInfo {
   StarSystem::BodySuperType supertype;
-  int         mass; /* % sol for stars, unused for planets. */
-  int         radius; /* % Sol radii for stars, % earth radii for planets. */
+  int         mass[2]; /* Min, max % sol for stars, unused for planets. */
+  int         radius;  /* % Sol radii for stars, % earth radii for planets. */
   const char *description;
   const char *icon;
   int tempMin, tempMax;
 } bodyTypeInfo[StarSystem::TYPE_MAX] = {
   {
-    StarSystem::SUPERTYPE_NONE, 0, 0, "You can't see me!",
+    StarSystem::SUPERTYPE_NONE, {}, 0, 0, "You can't see me!",
   },
   {
     StarSystem::SUPERTYPE_STAR,
-    40, 50, "Type 'M' red star",
+    {10, 47}, 50, "Type 'M' red star",
     "icons/object_star_m.png",
     2000, 3500
   },
   {
     StarSystem::SUPERTYPE_STAR,
-    80, 90, "Type 'K' orange star",
+    {50,78}, 90, "Type 'K' orange star",
     "icons/object_star_k.png",
     3500, 5000
   },
   {
     StarSystem::SUPERTYPE_STAR,
-    110, 110, "Type 'G' yellow star",
+    {80,110}, 110, "Type 'G' yellow star",
     "icons/object_star_g.png",
     5000, 6000
   },
   {
     StarSystem::SUPERTYPE_STAR,
-    170, 140, "Type 'F' white star",
+    {115,170}, 140, "Type 'F' white star",
     "icons/object_star_f.png",
     6000, 7500
   },
   {
     StarSystem::SUPERTYPE_STAR,
-    310, 210, "Type 'A' hot white star",
+    {180,320}, 210, "Type 'A' hot white star",
     "icons/object_star_a.png",
     7500, 10000
   },
   {
     StarSystem::SUPERTYPE_STAR,
-    1800, 700, "Bright type 'B' blue star",
+    {400,1000}, 700, "Bright type 'B' blue star",
     "icons/object_star_b.png",
     10000, 30000
   },
   {
     StarSystem::SUPERTYPE_STAR,
-    6400, 1600, "Hot, massive type 'O' blue star",
+    {2000,4000}, 1600, "Hot, massive type 'O' blue star",
     "icons/object_star_o.png",
     30000, 60000
   },
   {
     StarSystem::SUPERTYPE_GAS_GIANT,
-    0, 30, "Brown dwarf sub-stellar object",
+    {}, 30, "Brown dwarf sub-stellar object",
     "icons/object_brown_dwarf.png"
   },
   {
     StarSystem::SUPERTYPE_GAS_GIANT,
-    0, 390, "Small gas giant",
+    {}, 390, "Small gas giant",
     "icons/object_planet_small_gas_giant.png"
   },
   {
     StarSystem::SUPERTYPE_GAS_GIANT,
-    0, 950, "Medium gas giant",
+    {}, 950, "Medium gas giant",
     "icons/object_planet_medium_gas_giant.png"
   },
   {
     StarSystem::SUPERTYPE_GAS_GIANT,
-    0, 1110, "Large gas giant",
+    {}, 1110, "Large gas giant",
     "icons/object_planet_large_gas_giant.png"
   },
   {
     StarSystem::SUPERTYPE_GAS_GIANT,
-    0, 1500, "Very large gas giant",
+    {}, 1500, "Very large gas giant",
     "icons/object_planet_large_gas_giant.png"
   },
   {
     StarSystem::SUPERTYPE_ROCKY_PLANET,
-    0, 26, "Small, rocky dwarf planet",
+    {}, 26, "Small, rocky dwarf planet",
     "icons/object_planet_dwarf.png"
   },
   {
     StarSystem::SUPERTYPE_ROCKY_PLANET,
-    0, 52, "Small, rocky planet with a thin atmosphere",
+    {}, 52, "Small, rocky planet with a thin atmosphere",
     "icons/object_planet_small.png"
   },
   {
     StarSystem::SUPERTYPE_ROCKY_PLANET,
-    0, 100, "Rocky planet with liquid water and a nitrogen atmosphere",
+    {}, 100, "Rocky planet with liquid water and a nitrogen atmosphere",
     "icons/object_planet_small.png"
   },
   {
     StarSystem::SUPERTYPE_ROCKY_PLANET,
-    0, 100, "Rocky planet with a carbon dioxide atmosphere",
+    {}, 100, "Rocky planet with a carbon dioxide atmosphere",
     "icons/object_planet_small.png"
   },
   {
     StarSystem::SUPERTYPE_ROCKY_PLANET,
-    0, 100, "Rocky planet with a methane atmosphere",
+    {}, 100, "Rocky planet with a methane atmosphere",
     "icons/object_planet_small.png"
   },
   {
     StarSystem::SUPERTYPE_ROCKY_PLANET,
-    0, 100, "Rocky planet with running water and a thick nitrogen atmosphere",
+    {}, 100, "Rocky planet with running water and a thick nitrogen atmosphere",
     "icons/object_planet_small.png"
   },
   {
     StarSystem::SUPERTYPE_ROCKY_PLANET,
-    0, 100, "Rocky planet with a thick carbon dioxide atmosphere",
+    {}, 100, "Rocky planet with a thick carbon dioxide atmosphere",
     "icons/object_planet_small.png"
   },
   {
     StarSystem::SUPERTYPE_ROCKY_PLANET,
-    0, 100, "Rocky planet with a thick methane atmosphere",
+    {}, 100, "Rocky planet with a thick methane atmosphere",
     "icons/object_planet_small.png"
   },
   {
     StarSystem::SUPERTYPE_ROCKY_PLANET,
-    0, 100, "Highly volcanic world",
+    {}, 100, "Highly volcanic world",
     "icons/object_planet_small.png"
   },
   {
     StarSystem::SUPERTYPE_ROCKY_PLANET,
-    0, 100, "World with indigenous life and an oxygen atmosphere",
+    {}, 100, "World with indigenous life and an oxygen atmosphere",
     "icons/object_planet_life.png"
   }
 };
@@ -368,6 +369,66 @@ void StarSystem::GenerateFromCustom(const CustomSBody* customDef) {
   CustomGetChildOf(rootBody, customDef, idx);
 }
 
+void StarSystem::MakeStarOfType(SBody* sbody, BodyType type, MTRand& rand) {
+  sbody->type = type;
+  sbody->radius = fixed(bodyTypeInfo[type].radius, 100);
+  sbody->mass = fixed(rand.Int32(bodyTypeInfo[type].mass[0],
+        bodyTypeInfo[type].mass[1]), 100);
+  sbody->averageTemp = rand.Int32(bodyTypeInfo[type].tempMin,
+      bodyTypeInfo[type].tempMax);
+}
+
+void StarSystem::MakeRandomStar(SBody* sbody, MTRand& rand) {
+  BodyType type = (BodyType)rand.Int32((int)TYPE_STAR_MIN, (int)TYPE_STAR_MAX);
+  MakeStarOfType(sbody, type, rand);
+}
+
+void StarSystem::MakeRandomStarLighterThan(SBody* sbody, fixed maxMass, MTRand& rand) {
+  do {
+    MakeRandomStar(sbody, rand);
+  } while(sbody->mass > maxMass);
+}
+
+void StarSystem::MakeBinaryPair(SBody* a, SBody* b, fixed minDist, MTRand& rand) {
+  fixed ecc = rand.NFixed(3);
+  fixed m = a->mass + b->mass;
+  fixed a0 = b->mass / m;
+  fixed a1 = a->mass / m;
+  fixed semiMajorAxis;
+  int mul = 1;
+
+  do {
+    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;
+    }
+    semiMajorAxis *= mul;
+    mul *= 2;
+  } while(semiMajorAxis < minDist);
+
+  a->orbit.eccentricity = ecc.ToDouble();
+  a->orbit.semiMajorAxis = AU * (semiMajorAxis * a0).ToDouble();
+  a->orbit.period = 60*60*24*365*semiMajorAxis.ToDouble() * sqrt(semiMajorAxis.ToDouble() / m.ToDouble());
+
+  const float rotY = rand.Double()*M_PI/2.0;
+  const float rotZ = rand.Double(M_PI);
+  a->orbit.rotMatrix = matrix4x4d::RotateYMatrix(rotY) * matrix4x4d::RotateZMatrix(rotZ);
+  b->orbit.rotMatrix = matrix4x4d::RotateYMatrix(rotY) * matrix4x4d::RotateZMatrix(rotZ-M_PI);
+
+  b->orbit.eccentricity = ecc.ToDouble();
+  b->orbit.semiMajorAxis = AU * (semiMajorAxis * a1).ToDouble();
+  b->orbit.period = a->orbit.period;
+
+  fixed orbMin = semiMajorAxis - ecc*semiMajorAxis;
+  fixed orbMax = 2*semiMajorAxis - orbMin;
+  a->orbMin = orbMin;
+  b->orbMin = orbMin;
+  a->orbMax = orbMax;
+  b->orbMax = orbMax;
+}
+
 /*
  * Choices that depend on floating point values will result in
  * different universes on different platforms it seems.
@@ -395,13 +456,9 @@ StarSystem::StarSystem(int sector_x, int sector_y, int system_idx) {
   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;
+    MakeStarOfType(primary, type, rand);
     rootBody = primary;
   } else {
     SBody* centGrav = new SBody;
@@ -410,64 +467,70 @@ StarSystem::StarSystem(int sector_x, int sector_y, int system_idx) {
     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];
+    SBody* star[4];
     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);
+    
+    MakeStarOfType(star[0], type, rand);
 
-    /*
-     * 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());
+    MakeRandomStarLighterThan(star[1], star[0]->mass, rand);
 
-    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 orbMin = semiMajorAxis - ecc*semiMajorAxis;
-    fixed orbMax = 2*semiMajorAxis - orbMin;
-    star[0]->orbMin = orbMin;
-    star[1]->orbMin = orbMin;
-    star[0]->orbMax = orbMax;
-    star[1]->orbMax = orbMax;
+    MakeBinaryPair(star[0], star[1], fixed(0), rand);
 
+    centGrav->mass = star[0]->mass + star[1]->mass;
     centGrav->children.push_back(star[0]);
     centGrav->children.push_back(star[1]);
+
+    if((star[0]->orbMax < fixed(100, 1)) &&
+        (!rand.Int32(3))) {
+      SBody* centGrav2;
+      /* 3rd and maybe 4th star. */
+      if(!rand.Int32(2)) {
+        star[2] = new SBody;
+        star[2]->name = s.m_systems[system_idx].name+" C";
+        star[2]->orbMax = 0;
+        MakeRandomStarLighterThan(star[2], star[0]->mass, rand);
+        centGrav2 = star[2];
+      } else {
+        centGrav2 = new SBody;
+        centGrav2->type = TYPE_GRAVPOINT;
+        centGrav2->name = s.m_systems[system_idx].name;
+        centGrav2->orbMax = 0;
+
+        StarSystem::BodyType type = s.m_systems[system_idx].primaryStarClass;
+        star[2] = new SBody;
+        star[2]->name = s.m_systems[system_idx].name+" C";
+        star[2]->parent = centGrav2;
+        MakeRandomStarLighterThan(star[2], star[0]->mass, rand);
+
+        star[3] = new SBody;
+        star[3]->name = s.m_systems[system_idx].name+" D";
+        star[3]->parent = centGrav2;
+        MakeRandomStarLighterThan(star[3], star[2]->mass, rand);
+
+        MakeBinaryPair(star[2], star[3], fixed(0), rand);
+        centGrav2->mass = star[2]->mass + star[3]->mass;
+        centGrav2->children.push_back(star[2]);
+        centGrav2->children.push_back(star[3]);
+      }
+      SBody* superCentGrav = new SBody;
+      superCentGrav->type = TYPE_GRAVPOINT;
+      superCentGrav->parent = NULL;
+      superCentGrav->name = s.m_systems[system_idx].name;
+      centGrav->parent = superCentGrav;
+      centGrav2->parent = superCentGrav;
+      rootBody = superCentGrav;
+      const fixed minDist = star[0]->orbMax + star[2]->orbMax;
+      MakeBinaryPair(centGrav, centGrav2, 4*minDist, rand);
+      superCentGrav->children.push_back(centGrav);
+      superCentGrav->children.push_back(centGrav2);
+    }
     return;
   }
 
diff --git a/src/star_system.h b/src/star_system.h
index aa40b27..5700fa8 100644
--- a/src/star_system.h
+++ b/src/star_system.h
@@ -46,6 +46,7 @@ public:
     TYPE_STAR_A,
     TYPE_STAR_B,
     TYPE_STAR_O,
+    TYPE_WHITE_DWARF,
     TYPE_BROWN_DWARF,
     TYPE_PLANET_SMALL_GAS_GIANT,
     TYPE_PLANET_MEDIUM_GAS_GIANT,
@@ -61,7 +62,9 @@ public:
     TYPE_PLANET_METHANE_THICK_ATMOS,
     TYPE_PLANET_HIGHLY_VOLCANIC,
     TYPE_PLANET_INDIGENOUS_LIFE,
-    TYPE_MAX
+    TYPE_MAX,
+    TYPE_STAR_MIN = TYPE_STAR_M,
+    TYPE_STAR_MAX = TYPE_WHITE_DWARF
     /* TODO: Need larger atmosphereless thing. */
   };
 
@@ -122,6 +125,10 @@ public:
   SBody* rootBody;
 
 private:
+  void MakeRandomStar(SBody* sbody, MTRand& rand);
+  void MakeRandomStarLighterThan(SBody* sbody, fixed maxMass, MTRand& rand);
+  void MakeStarOfType(SBody* sbody, BodyType type, MTRand& rand);
+  void MakeBinaryPair(SBody* a, SBody* b, fixed minDist, MTRand& rand);
   void CustomGetChildOf(SBody* parent, const CustomSBody* customDef, const int parentIdx);
   void GenerateFromCustom(const CustomSBody*);
 
diff --git a/src/system_info_view.cpp b/src/system_info_view.cpp
index d776478..2f494c7 100644
--- a/src/system_info_view.cpp
+++ b/src/system_info_view.cpp
@@ -47,8 +47,10 @@ void SystemInfoView::OnBodySelected(StarSystem::SBody* b) {
     snprintf(buf, sizeof(buf), "Eccentricity    %.2f\n", b->orbit.eccentricity);
     desc += buf;
     const float dayLen = b->GetRotationPeriod();
-    if(dayLen) snprintf(buf, sizeof(buf), "Day length   %.1f earth days\n", dayLen/(60*60*24));
-    desc += buf;
+    if(dayLen) {
+      snprintf(buf, sizeof(buf), "Day length    %.1f earth days\n", dayLen/(60*60*24));
+      desc += buf;
+    }
   }
   m_infoText->SetText(desc);
 }
@@ -93,11 +95,15 @@ void SystemInfoView::SystemChanged(StarSystem* s) {
   }
 
   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++;
+    if((*i)->type == StarSystem::TYPE_GRAVPOINT) {
+
+    } else {
+      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())