diff --git a/Starsphere.cpp b/Starsphere.cpp
index 214cc6f863b1e1fe23bf4636253447f621da78b6..7d506b5a4d25531cbea6fae674ef288c9934ade9 100644
--- a/Starsphere.cpp
+++ b/Starsphere.cpp
@@ -28,6 +28,14 @@ Starsphere::Starsphere() : AbstractGraphicsEngine()
 	rotation_speed = 180.0;
 	
 	m_RefreshSearchMarker = true;
+	
+	m_XStartPosLeft = 0.008;
+	m_YStartPosTop = 0.975;
+	m_FontScaleLarge = 0.0225;
+	m_FontScaleMedium = 0.0131;
+	m_FontScaleSmall = 0.0131;
+	m_YOffsetLarge = 0.015;
+	m_YOffsetMedium = 0.015;
 }
 
 Starsphere::~Starsphere()
@@ -506,6 +514,9 @@ void Starsphere::resize(const int width, const int height)
  */
 void Starsphere::initialize(const int width, const int height, const Resource *font)
 {
+	// Initialize the BOINC client adapter
+	m_BoincAdapter.initialize("EinsteinHS");
+	
 	// setup initial dimensions
 	resize(width, height);
 	
@@ -688,17 +699,6 @@ void Starsphere::render(const double timeOfDay)
 	// draw 2D vectorized HUD
 	if(isFeature(LOGO) || isFeature(SEARCHINFO)) {
 	
-		static const GLfloat xStartPosLeft = 0.008;
-		const GLfloat xStartPosRight = 1 * aspect - 0.145;
-		static const GLfloat yStartPosTop = 0.975;
-		static const GLfloat yStartPosBottom = 0.07;
-		static const GLfloat fontScaleLarge = 0.0225;
-		static const GLfloat fontScaleMedium = 0.0131;
-		static const GLfloat fontScaleSmall = 0.0131;
-//		static const GLfloat yOffset = (font->Ascender() + font->Descender());
-		static const GLfloat yOffsetLarge = 0.015;
-		static const GLfloat yOffsetMedium = 0.015;
-
 		// disable depth testing since we're in 2D mode
 		glDisable(GL_DEPTH_TEST);
 		
@@ -718,7 +718,7 @@ void Starsphere::render(const double timeOfDay)
 			glPushMatrix();
 			
 			glColor3f(1.0, 1.0, 0.0);
-			glTranslatef(xStartPosLeft, yStartPosTop, 0);
+			glTranslatef(m_XStartPosLeft, m_YStartPosTop, 0);
 //			glScalef(fontScaleLarge, fontScaleLarge, 1.0);
 			glScalef(0.001, 0.001, 1.0);
 //			m_PolygonFont->Render("Einstein@Home");
@@ -730,76 +730,17 @@ void Starsphere::render(const double timeOfDay)
 
 			glLoadIdentity();
 			glColor4f(1.0, 1.0, 1.0, 0.5);
-			glTranslatef(xStartPosLeft, yStartPosTop - yOffsetLarge, 0);
-			glScalef(fontScaleMedium, fontScaleMedium, 1.0);
+			glTranslatef(m_XStartPosLeft, m_YStartPosTop - m_YOffsetLarge, 0);
+			glScalef(m_FontScaleMedium, m_FontScaleMedium, 1.0);
 			m_PolygonFont->Render("World Year of Physics 2005");
 			
 			glPopMatrix();
 		}
+		
 		if (isFeature(SEARCHINFO)) {
-			// left info block      
-			glPushMatrix();
-			
-			glColor3f(1.0, 1.0, 0.0);
-			glTranslatef(xStartPosLeft, yStartPosBottom, 0);
-			glScalef(fontScaleMedium, fontScaleMedium, 1.0);
-			m_PolygonFont->Render("BOINC Statistics");
-
-			glLoadIdentity();
-			glColor4f(1.0, 1.0, 1.0, 0.5);
-			glTranslatef(xStartPosLeft, yStartPosBottom - yOffsetMedium, 0);
-			glScalef(fontScaleSmall, fontScaleSmall, 1.0);
-			m_PolygonFont->Render(m_UserName.c_str());
-
-			glLoadIdentity();
-			glTranslatef(xStartPosLeft, yStartPosBottom - 2*yOffsetMedium, 0);
-			glScalef(fontScaleSmall, fontScaleSmall, 1.0);
-			m_PolygonFont->Render(m_TeamName.c_str());
-
-			glLoadIdentity();
-			glTranslatef(xStartPosLeft, yStartPosBottom - 3*yOffsetMedium, 0);
-			glScalef(fontScaleSmall, fontScaleSmall, 1.0);
-			m_PolygonFont->Render(m_UserCredit.c_str());
-
-			glLoadIdentity();
-			glTranslatef(xStartPosLeft, yStartPosBottom - 4*yOffsetMedium, 0);
-			glScalef(fontScaleSmall, fontScaleSmall, 1.0);
-			m_PolygonFont->Render(m_UserRACredit.c_str());
-			
-			glPopMatrix();
-	
-			// right info block
-			glPushMatrix();
-			
-			glColor3f(1.0, 1.0, 0.0);
-			glTranslatef(xStartPosRight, yStartPosBottom, 0);
-			glScalef(fontScaleMedium, fontScaleMedium, 1.0);
-			m_PolygonFont->Render("Search Information");
-
-			glLoadIdentity();
-			glColor4f(1.0, 1.0, 1.0, 0.5);
-			glTranslatef(xStartPosRight, yStartPosBottom - yOffsetMedium, 0);
-			glScalef(fontScaleSmall, fontScaleSmall, 1.0);
-			m_PolygonFont->Render(m_WUSkyPosRightAscension.c_str());
-
-			glLoadIdentity();
-			glTranslatef(xStartPosRight, yStartPosBottom - 2*yOffsetMedium, 0);
-			glScalef(fontScaleSmall, fontScaleSmall, 1.0);
-			m_PolygonFont->Render(m_WUSkyPosDeclination.c_str());
-
-			glLoadIdentity();
-			glTranslatef(xStartPosRight, yStartPosBottom - 3*yOffsetMedium, 0);
-			glScalef(fontScaleSmall, fontScaleSmall, 1.0);
-			m_PolygonFont->Render(m_WUPercentDone.c_str());
-
-			glLoadIdentity();
-			glTranslatef(xStartPosRight, yStartPosBottom - 4*yOffsetMedium, 0);
-			glScalef(fontScaleSmall, fontScaleSmall, 1.0);
-			m_PolygonFont->Render(m_WUCPUTime.c_str());
-			
-			glPopMatrix();
+			renderSearchInformation();
 		}
-	
+		
 		// restore original state
 		glMatrixMode(GL_PROJECTION);
 		glPopMatrix();
@@ -940,38 +881,4 @@ void Starsphere::refreshBOINCInformation()
 	buffer << "Project RAC: " << fixed << m_BoincAdapter.userRACredit() << ends;
 	m_UserRACredit = buffer.str();
 	buffer.str("");
-
-	// store content required for our HUD (search info)
-	if(m_CurrentRightAscension != m_BoincAdapter.wuSkyPosRightAscension()) {
-		// we've got a new position, update search marker and HUD
-		m_CurrentRightAscension = m_BoincAdapter.wuSkyPosRightAscension();
-		m_RefreshSearchMarker = true;
-		buffer << "Ascension: " << fixed << m_CurrentRightAscension * 360/PI2 << " deg" << ends;
-		m_WUSkyPosRightAscension = buffer.str();
-		buffer.str("");
-	}
-	
-	if(m_CurrentDeclination != m_BoincAdapter.wuSkyPosDeclination()) {
-		// we've got a new position, update search marker and HUD
-		m_CurrentDeclination = m_BoincAdapter.wuSkyPosDeclination();
-		m_RefreshSearchMarker = true;
-		buffer << "Declination: " << fixed << m_CurrentDeclination * 360/PI2 << " deg" << ends;
-		m_WUSkyPosDeclination = buffer.str();
-		buffer.str("");
-	}
-	
-	buffer << "Completed: " << fixed << m_BoincAdapter.wuFractionDone() * 100 << " %" << ends;
-	m_WUPercentDone = buffer.str();
-	buffer.str("");
-	
-	const double cputime = m_BoincAdapter.wuCPUTime();
-	const int hrs =  cputime / 3600;
-	const int min = (cputime - hrs*3600) / 60;
-	const int sec =  cputime - (hrs*3600 + min*60);	
-
-	buffer << "CPU Time: "  << right << setw(2) << hrs << ":"
-							<< right << setw(2) << min << ":"
-							<< right << setw(2) << sec << ends;
-	
-	m_WUCPUTime = buffer.str();
 }
diff --git a/Starsphere.h b/Starsphere.h
index 04b102dff63aa5facd08696a1015adb7c553a0ea..bfef8d882412a989595bc03552dca78656ea4f1c 100644
--- a/Starsphere.h
+++ b/Starsphere.h
@@ -38,7 +38,6 @@ using namespace std;
 class Starsphere : public AbstractGraphicsEngine
 {
 public:
-	Starsphere();
 	virtual ~Starsphere();
 
 	// core methods
@@ -52,7 +51,39 @@ public:
 	void keyboardPressEvent(const int keyPressed);
 	
 	// update HUD content
-	void refreshBOINCInformation();
+	virtual void refreshBOINCInformation();
+	
+protected:
+	/// Contructor (protected since this an abstract class)	
+	Starsphere();
+	
+
+	// resource handling
+	FTFont *m_PolygonFont;
+	OGLFT::TranslucentTexture* face;
+	
+	// Graphics state info:
+	float aspect;
+	
+	// HUD text rendering config (maybe overridden in subclasses)
+	GLfloat m_XStartPosLeft;
+	GLfloat m_YStartPosTop;
+	GLfloat m_FontScaleLarge;
+	GLfloat m_FontScaleMedium;
+	GLfloat m_FontScaleSmall;
+	GLfloat m_YOffsetLarge;
+	GLfloat m_YOffsetMedium;
+	
+	// local HUD contents
+	string m_UserName;
+	string m_TeamName;
+	string m_UserCredit;
+	string m_UserRACredit;
+	
+	// search marker info
+	double m_CurrentRightAscension;
+	double m_CurrentDeclination;
+	bool m_RefreshSearchMarker;
 	
 private:
 	void make_stars();
@@ -98,11 +129,11 @@ private:
 	GLfloat rotation_offset; // so that we can rotate sphere
 	GLfloat rotation_speed; // degrees per minute
 
-	// Graphics state info:
-	float aspect;
-	
 	//------------ new clean members -----
 	
+	// application specific rendering
+	virtual void renderSearchInformation() = 0;
+	
 	// view control
 	void rotateSphere(const int relativeRotation, const int relativeElevation);
 	void zoomSphere(const int relativeZoom);
@@ -125,25 +156,6 @@ private:
 		MARKER = 1024
 	};
 
-	// resource handling
-	FTFont *m_PolygonFont;
-	OGLFT::TranslucentTexture* face;
-	
-	// local HUD contents
-	string m_UserName;
-	string m_TeamName;
-	string m_UserCredit;
-	string m_UserRACredit;
-	string m_WUSkyPosRightAscension;
-	string m_WUSkyPosDeclination;
-	string m_WUPercentDone;
-	string m_WUCPUTime;
-	
-	// search marker info
-	double m_CurrentRightAscension;
-	double m_CurrentDeclination;
-	bool m_RefreshSearchMarker;
-	
 	// observatory movement
 	// (in seconds since 1970 with usec precision)
 	double m_ObservatoryDrawTimeLocal;
diff --git a/StarsphereS5R3.cpp b/StarsphereS5R3.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..aa97f14555e768433e795be10414009a63026441
--- /dev/null
+++ b/StarsphereS5R3.cpp
@@ -0,0 +1,123 @@
+#include "StarsphereS5R3.h"
+
+StarsphereS5R3::StarsphereS5R3() : m_EinsteinAdapter(&m_BoincAdapter)
+{
+	m_YStartPosBottom = 0.07;
+}
+
+StarsphereS5R3::~StarsphereS5R3()
+{
+}
+
+void StarsphereS5R3::refreshBOINCInformation()
+{
+	Starsphere::refreshBOINCInformation();
+	
+	// prepare conversion buffer
+	stringstream buffer;
+	buffer.precision(2);
+	buffer.setf(ios::fixed, ios::floatfield);
+	buffer.fill('0');
+	buffer.setf(ios::right, ios::adjustfield);
+	
+	// store content required for our HUD (search info)
+	if(m_CurrentRightAscension != m_EinsteinAdapter.wuSkyPosRightAscension()) {
+		// we've got a new position, update search marker and HUD
+		m_CurrentRightAscension = m_EinsteinAdapter.wuSkyPosRightAscension();
+		m_RefreshSearchMarker = true;
+		buffer << "Ascension: " << fixed << m_CurrentRightAscension * 360/PI2 << " deg" << ends;
+		m_WUSkyPosRightAscension = buffer.str();
+		buffer.str("");
+	}
+	
+	if(m_CurrentDeclination != m_EinsteinAdapter.wuSkyPosDeclination()) {
+		// we've got a new position, update search marker and HUD
+		m_CurrentDeclination = m_EinsteinAdapter.wuSkyPosDeclination();
+		m_RefreshSearchMarker = true;
+		buffer << "Declination: " << fixed << m_CurrentDeclination * 360/PI2 << " deg" << ends;
+		m_WUSkyPosDeclination = buffer.str();
+		buffer.str("");
+	}
+	
+	buffer << "Completed: " << fixed << m_EinsteinAdapter.wuFractionDone() * 100 << " %" << ends;
+	m_WUPercentDone = buffer.str();
+	buffer.str("");
+	
+	const double cputime = m_EinsteinAdapter.wuCPUTime();
+	const int hrs =  cputime / 3600;
+	const int min = (cputime - hrs*3600) / 60;
+	const int sec =  cputime - (hrs*3600 + min*60);	
+
+	buffer << "CPU Time: "  << right << setw(2) << hrs << ":"
+							<< right << setw(2) << min << ":"
+							<< right << setw(2) << sec << ends;
+	
+	m_WUCPUTime = buffer.str();	
+}
+
+void StarsphereS5R3::renderSearchInformation()
+{
+		m_XStartPosRight = 1 * aspect - 0.145;
+	
+		// left info block      
+		glPushMatrix();
+		
+		glColor3f(1.0, 1.0, 0.0);
+		glTranslatef(m_XStartPosLeft, m_YStartPosBottom, 0);
+		glScalef(m_FontScaleMedium, m_FontScaleMedium, 1.0);
+		m_PolygonFont->Render("BOINC Statistics");
+	
+		glLoadIdentity();
+		glColor4f(1.0, 1.0, 1.0, 0.5);
+		glTranslatef(m_XStartPosLeft, m_YStartPosBottom - m_YOffsetMedium, 0);
+		glScalef(m_FontScaleSmall, m_FontScaleSmall, 1.0);
+		m_PolygonFont->Render(m_UserName.c_str());
+	
+		glLoadIdentity();
+		glTranslatef(m_XStartPosLeft, m_YStartPosBottom - 2*m_YOffsetMedium, 0);
+		glScalef(m_FontScaleSmall, m_FontScaleSmall, 1.0);
+		m_PolygonFont->Render(m_TeamName.c_str());
+	
+		glLoadIdentity();
+		glTranslatef(m_XStartPosLeft, m_YStartPosBottom - 3*m_YOffsetMedium, 0);
+		glScalef(m_FontScaleSmall, m_FontScaleSmall, 1.0);
+		m_PolygonFont->Render(m_UserCredit.c_str());
+	
+		glLoadIdentity();
+		glTranslatef(m_XStartPosLeft, m_YStartPosBottom - 4*m_YOffsetMedium, 0);
+		glScalef(m_FontScaleSmall, m_FontScaleSmall, 1.0);
+		m_PolygonFont->Render(m_UserRACredit.c_str());
+		
+		glPopMatrix();
+	
+		// right info block
+		glPushMatrix();
+		
+		glColor3f(1.0, 1.0, 0.0);
+		glTranslatef(m_XStartPosRight, m_YStartPosBottom, 0);
+		glScalef(m_FontScaleMedium, m_FontScaleMedium, 1.0);
+		m_PolygonFont->Render("Search Information");
+	
+		glLoadIdentity();
+		glColor4f(1.0, 1.0, 1.0, 0.5);
+		glTranslatef(m_XStartPosRight, m_YStartPosBottom - m_YOffsetMedium, 0);
+		glScalef(m_FontScaleSmall, m_FontScaleSmall, 1.0);
+		m_PolygonFont->Render(m_WUSkyPosRightAscension.c_str());
+	
+		glLoadIdentity();
+		glTranslatef(m_XStartPosRight, m_YStartPosBottom - 2*m_YOffsetMedium, 0);
+		glScalef(m_FontScaleSmall, m_FontScaleSmall, 1.0);
+		m_PolygonFont->Render(m_WUSkyPosDeclination.c_str());
+	
+		glLoadIdentity();
+		glTranslatef(m_XStartPosRight, m_YStartPosBottom - 3*m_YOffsetMedium, 0);
+		glScalef(m_FontScaleSmall, m_FontScaleSmall, 1.0);
+		m_PolygonFont->Render(m_WUPercentDone.c_str());
+	
+		glLoadIdentity();
+		glTranslatef(m_XStartPosRight, m_YStartPosBottom - 4*m_YOffsetMedium, 0);
+		glScalef(m_FontScaleSmall, m_FontScaleSmall, 1.0);
+		m_PolygonFont->Render(m_WUCPUTime.c_str());
+		
+		glPopMatrix();
+}
diff --git a/StarsphereS5R3.h b/StarsphereS5R3.h
new file mode 100644
index 0000000000000000000000000000000000000000..e7e336390d4cdab4d37b0c6dff555e61b038ebae
--- /dev/null
+++ b/StarsphereS5R3.h
@@ -0,0 +1,33 @@
+#ifndef STARSPHERES5R3_H_
+#define STARSPHERES5R3_H_
+
+#include <sstream>
+
+#include "Starsphere.h"
+#include "EinsteinS5R3Adapter.h"
+
+using namespace std;
+
+class StarsphereS5R3 : public Starsphere
+{
+public:
+	StarsphereS5R3();
+	virtual ~StarsphereS5R3();
+	
+	void refreshBOINCInformation();
+	
+private:
+	void renderSearchInformation();
+	
+	EinsteinS5R3Adapter m_EinsteinAdapter;
+	
+	string m_WUSkyPosRightAscension;
+	string m_WUSkyPosDeclination;
+	string m_WUPercentDone;
+	string m_WUCPUTime;
+	
+	GLfloat m_XStartPosRight;
+	GLfloat m_YStartPosBottom;
+};
+
+#endif /*STARSPHERES5R3_H_*/