diff --git a/icons/cpan_f2_normal.png b/icons/cpan_f2_normal.png
index a791b57..79f948c 100644
Binary files a/icons/cpan_f2_normal.png and b/icons/cpan_f2_normal.png differ
diff --git a/icons/cpan_f3_shipinfo.png b/icons/cpan_f3_shipinfo.png
new file mode 100644
index 0000000..843b9a9
Binary files /dev/null and b/icons/cpan_f3_shipinfo.png differ
diff --git a/src/Makefile.am b/src/Makefile.am
index 377397f..797898d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -7,7 +7,8 @@ Lephisto3D_SOURCES	= main.cpp gui_button.cpp gui.cpp gui_fixed.cpp gui_screen.cp
 		gui_radio_group.cpp rigid_body.cpp planet.cpp star.cpp frame.cpp gui_image_button.cpp gui_image.cpp \
 		gui_image_radio_button.cpp gui_multi_state_image_button.cpp ship_cpanel.cpp gui_widget.cpp sector_view.cpp \
 		mtrand.cpp world_view.cpp system_view.cpp star_system.cpp sector.cpp system_info_view.cpp generic_system_view.cpp \
-		gui_container.cpp date.cpp space_station.cpp space_station_view.cpp static_rigid_body.cpp ship_type.cpp
+		gui_container.cpp date.cpp space_station.cpp space_station_view.cpp static_rigid_body.cpp ship_type.cpp \
+                info_view.cpp
 Lephisto3D_LDADD = sbre/libsbre.a
 
 include_HEADERS = body.h frame.h generic_system_view.h glfreetype.h gui_button.h gui_container.h gui_events.h gui_fixed.h \
@@ -15,5 +16,5 @@ include_HEADERS = body.h frame.h generic_system_view.h glfreetype.h gui_button.h
 		gui_radio_group.h gui_screen.h gui_toggle_button.h gui_widget.h libs.h matrix4x4.h mtrand.h objimport.h l3d.h \
 		planet.h player.h rigid_body.h sector.h sector_view.h ship_cpanel.h ship.h space.h star.h star_system.h system_info_view.h \
 		system_view.h vector3.h view.h world_view.h date.h space_station.h space_station_view.h static_rigid_body.h gui_iselectable.h \
-		ship_type.h object.h
+		ship_type.h object.h info_view.h
 
diff --git a/src/info_view.cpp b/src/info_view.cpp
new file mode 100644
index 0000000..965ed5d
--- /dev/null
+++ b/src/info_view.cpp
@@ -0,0 +1,46 @@
+#include "info_view.h"
+#include "l3d.h"
+#include "player.h"
+#include "world_view.h"
+#include "ship.h"
+
+InfoView::InfoView(void) : View() {
+  SetTransparency(false);
+  SetBgColor(.0, .2, .4);
+
+  float size[2];
+  GetSize(size);
+
+  info1 = new Gui::Label("Some star stuff.");
+  Add(info1, 40, size[1]-40);
+}
+
+void InfoView::UpdateInfo(void) {
+  char buf[512];
+  std::string nfo;
+  const ShipType& stype = L3D::player->GetShipType();
+  nfo = "SHIP INFORMATION: "+std::string(stype.name);
+
+  Equip::Type e = L3D::player->m_equipment.Get(Equip::SLOT_ENGINE);
+  nfo += std::string("\n\nDrive system:   ")+EquipType::types[e].name;
+
+  shipstats_t stats;
+  L3D::player->CalcStats(&stats);
+  snprintf(buf, sizeof(buf), "n\nCapacity:    %dt\n"
+                             "Free:   %dt\n"
+                             "Used:   %dt\n"
+                             "All-up weight:    %dt", stats.max_capacity,
+                             stats.free_capacity, stats.used_capacity,
+                             stats.total_mass);
+  nfo += std::string(buf);
+  info1->SetText(nfo);
+}
+
+void InfoView::Draw3D(void) {
+
+}
+
+void InfoView::Update(void) {
+
+}
+
diff --git a/src/info_view.h b/src/info_view.h
new file mode 100644
index 0000000..cdf66d5
--- /dev/null
+++ b/src/info_view.h
@@ -0,0 +1,15 @@
+#pragma once
+#include "libs.h"
+#include "gui.h"
+#include "view.h"
+
+class InfoView : public View {
+public:
+  InfoView(void);
+  void UpdateInfo(void);
+  virtual void Update(void);
+  virtual void Draw3D(void);
+private:
+  Gui::Label* info1;
+};
+
diff --git a/src/l3d.h b/src/l3d.h
index 50032d6..6273839 100644
--- a/src/l3d.h
+++ b/src/l3d.h
@@ -14,6 +14,7 @@ class SystemInfoView;
 class ShipCpanel;
 class StarSystem;
 class SpaceStationView;
+class InfoView;
 
 class IniConfig: private std::map<std::string, std::string> {
 public:
@@ -73,7 +74,7 @@ public:
   static SystemInfoView*    system_info_view;
   static WorldView*         world_view;
   static SpaceStationView*  spaceStationView;
-
+  static InfoView*          infoView;
   static ShipCpanel*        cpan;
   static GLUquadric*        gluQuadric;
 
diff --git a/src/main.cpp b/src/main.cpp
index 4a0bf9b..d4f350a 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -16,6 +16,7 @@
 #include "star_system.h"
 #include "space_station.h"
 #include "space_station_view.h"
+#include "info_view.h"
 
 float             L3D::timeStep = 1.0f;
 int               L3D::scrWidth;
@@ -35,6 +36,7 @@ Player*           L3D::player;
 View*             L3D::current_view;
 WorldView*        L3D::world_view;
 SpaceStationView* L3D::spaceStationView;
+InfoView*         L3D::infoView;
 SectorView*       L3D::sector_view;
 SystemView*       L3D::system_view;
 SystemInfoView*   L3D::system_info_view;
@@ -234,6 +236,7 @@ void L3D::MainLoop(void) {
   system_info_view  = new SystemInfoView();
   world_view        = new WorldView();
   spaceStationView  = new SpaceStationView();
+  infoView          = new InfoView();
 
   SetView(world_view);
 
diff --git a/src/planet.cpp b/src/planet.cpp
index 7d94c2b..f83ddbd 100644
--- a/src/planet.cpp
+++ b/src/planet.cpp
@@ -7,6 +7,7 @@ Planet::Planet(StarSystem::SBody::SubType subtype) : Body() {
   m_radius  = 6378135.0;
   m_pos     = vector3d(0, 0, 0);
   m_geom    = dCreateSphere(0, m_radius);
+  dGeomSetData(m_geom, static_cast<Body*>(this));
   m_subtype = subtype;
 }
 
diff --git a/src/planet.h b/src/planet.h
index c56f2f7..50588f9 100644
--- a/src/planet.h
+++ b/src/planet.h
@@ -15,6 +15,7 @@ public:
   virtual void TransformToModelCoords(const Frame* camFrame);
   virtual void TransformCameraTo(void) {};
   virtual void SetFrame(Frame* f);
+  virtual bool OnCollision(Body* b) { return true; }
 private:
   vector3d m_pos;
   double m_radius;
diff --git a/src/player.cpp b/src/player.cpp
index e123cab..84fc18c 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -12,6 +12,8 @@ Player::Player(ShipType::Type shipType) : Ship(shipType) {
   m_external_view_rotx = m_external_view_roty = 0;
   m_external_view_dist = 200;
   m_mouseCMov[0] = m_mouseCMov[1] = 0;
+  m_equipment.Set(Equip::SLOT_ENGINE, 0, Equip::DRIVE_CLASS1);
+  UpdateMass();
 }
 
 void Player::Render(const Frame* camFrame) {
@@ -65,17 +67,17 @@ void Player::AITurn(void) {
   if(time_step == 0)  return;
   if(GetDockedWith()) return;
 
-  float mx, my;
+  vector3f angThrust(0.0f);
 
-  {
+  if(L3D::MouseButtonState(3)) {
     float restitution = powf(MOUSE_RESTITUTION, time_step);
     L3D::GetMouseMotion(mouseMotion);
     m_mouseCMov[0] += mouseMotion[0];
     m_mouseCMov[1] += mouseMotion[1];
     m_mouseCMov[0] = CLAMP(m_mouseCMov[0]*restitution, -MOUSE_CTRL_AREA, MOUSE_CTRL_AREA);
     m_mouseCMov[1] = CLAMP(m_mouseCMov[1]*restitution, -MOUSE_CTRL_AREA, MOUSE_CTRL_AREA);
-    mx = -m_mouseCMov[0] / MOUSE_CTRL_AREA;
-    my =  m_mouseCMov[1] / MOUSE_CTRL_AREA;
+    angThrust.y = -m_mouseCMov[0] / MOUSE_CTRL_AREA;
+    angThrust.x =  m_mouseCMov[1] / MOUSE_CTRL_AREA;
   }
 
   ClearThrusterState();
@@ -91,30 +93,32 @@ void Player::AITurn(void) {
 
   /* No torques at huge time accels -- ODE hates it. */
   if(time_step <= 10) {
+    if(L3D::GetCamType() != L3D::CAM_EXTERNAL) {
+      if(L3D::KeyState(SDLK_LEFT))  angThrust.y +=  1;
+      if(L3D::KeyState(SDLK_RIGHT)) angThrust.y += -1;
+      if(L3D::KeyState(SDLK_UP))    angThrust.x += -1;
+      if(L3D::KeyState(SDLK_DOWN))  angThrust.x +=  1;
+    }
+    /* Rotation damping. */
+    const dReal* _av = dBodyGetAngularVel(m_body);
+    vector3d angVel(_av[0], _av[1], _av[2]);
+    matrix4x4d rot;
+    GetRotMatrix(rot);
+    angVel = rot.InverseOf() * angVel;
+
+    angVel *= 0.4;
+    angThrust.x -= angVel.x;
+    angThrust.y -= angVel.y;
+    angThrust.z -= angVel.z;
+
     /*
-     * Dividing by time step so controls don't go totally mental when
+     * Divided by time step so controls don't go totally insane when
      * used at 10x accel.
      */
-     mx /= ts2;
-     my /= ts2;
-     if(L3D::MouseButtonState(3)) {
-      SetAngThrusterState(1, mx);
-      SetAngThrusterState(0, my);
-     } else if(L3D::GetCamType() != L3D::CAM_EXTERNAL) {
-      float ax = 0;
-      float ay = 0;
-      if(L3D::KeyState(SDLK_LEFT))   ay +=  1;
-      if(L3D::KeyState(SDLK_RIGHT))  ay += -1;
-      if(L3D::KeyState(SDLK_UP))     ax += -1;
-      if(L3D::KeyState(SDLK_DOWN))   ax +=  1;
-      SetAngThrusterState(2, 0);
-      SetAngThrusterState(1, ay);
-      SetAngThrusterState(0, ax);
-     }
-
-     /* Rotation damping. */
-     vector3d angDrag = GetAngularMomentum() * time_step;
-     dBodyAddTorque(m_body, -angDrag.x, -angDrag.y, -angDrag.z);
+    angThrust *= 1.0f/ts2;
+    SetAngThrusterState(0, angThrust.x);
+    SetAngThrusterState(1, angThrust.y);
+    SetAngThrusterState(2, angThrust.z);
   }
   if(time_step > 10) {
     dBodySetAngularVel(m_body, 0, 0, 0);
diff --git a/src/ship.cpp b/src/ship.cpp
index 7615b22..a1a19f3 100644
--- a/src/ship.cpp
+++ b/src/ship.cpp
@@ -12,6 +12,7 @@ Ship::Ship(ShipType::Type shipType) : RigidBody() {
   m_shipType = shipType;
   m_angThrusters[0] = m_angThrusters[1] = m_angThrusters[2] = 0;
   m_laserCollisionObj.owner = this;
+  m_equipment = EquipSet(shipType);
   for(int i = 0; i < ShipType::GUNMOUNT_MAX; i++) {
     m_tempLaserGeom[i] = 0;
     m_gunState[i] = 0;
@@ -19,6 +20,12 @@ Ship::Ship(ShipType::Type shipType) : RigidBody() {
   dGeomSetData(m_geom, static_cast<Body*>(this));
 }
 
+void Ship::UpdateMass(void) {
+  shipstats_t s;
+  CalcStats(&s);
+  dMassAdjust(&m_mass, s.total_mass*1000);
+}
+
 void Ship::SetThrusterState(enum ShipType::Thruster t, float level) {
   m_thrusters[t] = level;
 }
@@ -27,6 +34,24 @@ void Ship::ClearThrusterState(void) {
   for(int i = 0; i < ShipType::THRUSTER_MAX; i++) m_thrusters[i] = 0;
 }
 
+/* Hyperspace range is:
+ * (200 * hyperspace_class^2) / total_mass (in tonnes)
+ */
+void Ship::CalcStats(shipstats_t* stats) {
+  const ShipType& stype = GetShipType();
+  stats->max_capacity = stype.capacity;
+  stats->used_capacity = 0;
+
+  for(int i = 0; i < Equip::SLOT_MAX; i++) {
+    for(int j = 0; j < stype.equipSlotCapacity[i]; j++) {
+      Equip::Type t = m_equipment.Get((Equip::Slot)i, j);
+      if(t) stats->used_capacity += EquipType::types[t].mass;
+    }
+  }
+  stats->free_capacity = stats->max_capacity - stats->used_capacity;
+  stats->total_mass = stats->used_capacity + stype.hullMass;
+}
+
 void Ship::AITurn(void) {
   const ShipType& stype = GetShipType();
   float timeStep = L3D::GetTimeStep();
@@ -55,7 +80,6 @@ void Ship::AITurn(void) {
     m_tempLaserGeom[i] = 0;
     if(!m_gunState[i]) continue;
     dGeomID ray = dCreateRay(GetFrame()->GetSpaceID(), 10000);
-    const dReal* r = dGeomGetRotation(m_geom);
     const vector3d pos = GetPosition();
     const vector3f _dir = stype.gunMount[i].dir;
     vector3d dir = vector3d(_dir.x, _dir.y, _dir.z);
diff --git a/src/ship.h b/src/ship.h
index bb1a581..43f09ae 100644
--- a/src/ship.h
+++ b/src/ship.h
@@ -5,6 +5,14 @@
 
 class SpaceStation;
 
+struct shipstats_t {
+  int max_capacity;
+  int used_capacity;
+  int free_capacity;
+  int total_mass; /* Cargo, equipment + hull. */
+  float hyperspace_range;
+};
+
 class Ship : public RigidBody {
 public:
   Ship(ShipType::Type shipType);
@@ -18,16 +26,20 @@ public:
   void SetAngThrusterState(int axis, float level) { m_angThrusters[axis] = CLAMP(level, -1, 1); }
   void ClearThrusterState(void);
   void SetGunState(int idx, int state);
+  const ShipType& GetShipType(void);
+  void CalcStats(shipstats_t* stats);
+  void UpdateMass(void);
 
   class LaserObj : public Object {
   public:
     virtual Object::Type GetType(void) { return Object::LASER; }
     Ship* owner;
   };
+
+  EquipSet m_equipment;
 protected:
   void RenderLaserfire(void);
   
-  const ShipType& GetShipType(void);
   SpaceStation* m_dockedWith;
   enum ShipType::Type m_shipType;
   ObjMesh* m_mesh;
diff --git a/src/ship_cpanel.cpp b/src/ship_cpanel.cpp
index 20906a0..154add6 100644
--- a/src/ship_cpanel.cpp
+++ b/src/ship_cpanel.cpp
@@ -3,6 +3,7 @@
 #include "ship_cpanel.h"
 #include "space_station_view.h"
 #include "player.h"
+#include "info_view.h"
 
 ShipCpanel::ShipCpanel(void) : Gui::Fixed(0, 0, 640, 64) {
   //SetBgColor(1, 0, 0);
@@ -59,6 +60,14 @@ ShipCpanel::ShipCpanel(void) : Gui::Fixed(0, 0, 640, 64) {
   map_button->onClick.connect(sigc::mem_fun(this, &ShipCpanel::OnChangeMapView));
   Add(map_button, 34, 2);
 
+  Gui::MultiStateImageButton* info_button = new Gui::MultiStateImageButton();
+  g->Add(info_button);
+  info_button->SetSelected(false);
+  info_button->SetShortcut(SDLK_F3, KMOD_NONE);
+  info_button->AddState(0, "icons/cpan_f3_shipinfo.png");
+  info_button->onClick.connect(sigc::mem_fun(this, &ShipCpanel::OnChangeInfoView));
+  Add(info_button, 66, 2);
+
   Gui::ImageButton* comms_button = new Gui::ImageButton("icons/comms_f4.png");
   //g->Add(comms_button);
   comms_button->SetShortcut(SDLK_F4, KMOD_NONE);
@@ -88,6 +97,11 @@ void ShipCpanel::OnChangeCamView(Gui::MultiStateImageButton* b) {
   L3D::SetCamType((enum L3D::CamType)b->GetState());
 }
 
+void ShipCpanel::OnChangeInfoView(Gui::MultiStateImageButton* b) {
+  L3D::infoView->UpdateInfo();
+  L3D::SetView(L3D::infoView);
+}
+
 void ShipCpanel::OnChangeMapView(Gui::MultiStateImageButton* b) {
   L3D::SetMapView((enum L3D::MapView)b->GetState());
 }
diff --git a/src/ship_cpanel.h b/src/ship_cpanel.h
index b5fdf77..f619df9 100644
--- a/src/ship_cpanel.h
+++ b/src/ship_cpanel.h
@@ -10,6 +10,7 @@ public:
 private:
   void OnChangeCamView(Gui::MultiStateImageButton* b);
   void OnChangeMapView(Gui::MultiStateImageButton* b);
+  void OnChangeInfoView(Gui::MultiStateImageButton* b);
   void OnClickTimeaccel(Gui::ISelectable* i, double step);
   void OnClickComms(void);
 
diff --git a/src/ship_type.cpp b/src/ship_type.cpp
index ffa757a..c2f7bc2 100644
--- a/src/ship_type.cpp
+++ b/src/ship_type.cpp
@@ -8,11 +8,13 @@ const ShipType ShipType::types[] = {
      */
     "Sirius Interdictor", 10,
     { 250, -250, 50, -50, -50, 50 },
-    700.0,
+    2000.0,
     {
       { vector3f(0, -0.5, 0), vector3f(0, 0, -1) },
       { vector3f(0, 0, 0), vector3f(0, 0, 1) }
-    }
+    },
+    { 1, 2, 0 },
+    100, 20,
   },
   {
     /*
@@ -25,7 +27,9 @@ const ShipType ShipType::types[] = {
     {
       { vector3f(0, -0.5, 0), vector3f(0, 0, -1) },
       { vector3f(0, 0, 0), vector3f(0, 0, 1) }
-    }
+    },
+    { 1, 1, 0 },
+    60, 15,
   },
   {
     "Flowerfairy Heavy Trader",
@@ -35,7 +39,32 @@ const ShipType ShipType::types[] = {
     {
       { vector3f(0, -0.5, 0), vector3f(0, 0, -1) },
       { vector3f(0, 0, 0),    vector3f(0, 0,  1) }
-    }
+    },
+    { 1, 2, 0 },
+    500, 125,
+  }
+};
+
+const EquipType EquipType::types[] = {
+  { 
+    "None",
+    Equip::SLOT_ENGINE,
+    0,
+  },
+  {
+    "Interplanetary Drive",
+    Equip::SLOT_ENGINE,
+    1
+  },
+  {
+    "Class 1 Hyperdrive",
+    Equip::SLOT_ENGINE,
+    4
+  },
+  {
+    "1MW beam laser",
+    Equip::SLOT_LASER,
+    1
   }
 };
 
diff --git a/src/ship_type.h b/src/ship_type.h
index b62b447..73c3b08 100644
--- a/src/ship_type.h
+++ b/src/ship_type.h
@@ -1,9 +1,14 @@
 #pragma once
+#include <vector>
 #include "libs.h"
 #include "vector3.h"
 
+namespace Equip {
+  enum Slot { SLOT_ENGINE, SLOT_LASER, SLOT_MISSILE, SLOT_MAX };
+  enum Type { NONE, DRIVE_INTERPLANETARY, DRIVE_CLASS1, LASER_1MW_BEAM };
+};
+
 struct ShipType {
-public:
   enum Thruster { THRUSTER_FRONT, THRUSTER_REAR, THRUSTER_TOP, THRUSTER_BOTTOM,
                   THRUSTER_LEFT, THRUSTER_RIGHT, THRUSTER_MAX };
   enum Type { SLEEK, LADYBIRD, FLOWERFAIRY };
@@ -18,8 +23,40 @@ public:
     vector3f pos;
     vector3f dir;
   } gunMount[GUNMOUNT_MAX];
+  int equipSlotCapacity[Equip::SLOT_MAX];
+  int capacity; /* Tonnes. */
+  int hullMass;
   /*******************************/
   
   static const ShipType types[];
 };
 
+class EquipSet {
+public:
+  EquipSet(void) {}
+  EquipSet(ShipType::Type t) {
+    for(int i = 0; i < Equip::SLOT_MAX; i++) {
+      equip[i] = std::vector<Equip::Type>(ShipType::types[t].equipSlotCapacity[i]);
+    }
+  }
+  Equip::Type Get(Equip::Slot s) {
+    return equip[s][0];
+  }
+  Equip::Type Get(Equip::Slot s, int idx) {
+    return equip[s][idx];
+  }
+  void Set(Equip::Slot s, int idx, Equip::Type e) {
+    equip[s][idx] = e;
+  }
+private:
+  std::vector<Equip::Type> equip[Equip::SLOT_MAX];
+};
+
+struct EquipType {
+  const char* name;
+  Equip::Slot slot;
+  int         mass;
+
+  static const EquipType types[];
+};
+