diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/Events/EventRouter.cc ./Events/EventRouter.cc
--- ../Tekkotsu_2.4/Events/EventRouter.cc	Thu Jul  7 18:34:15 2005
+++ ./Events/EventRouter.cc	Tue Aug 16 14:43:04 2005
@@ -1,5 +1,7 @@
 #include "EventRouter.h"
 #include "Shared/Profiler.h"
+#include "Behaviors/BehaviorBase.h"
+#include "Shared/ProjectInterface.h"
 #include <algorithm>
 
 EventRouter * erouter=NULL;
@@ -26,8 +28,28 @@
 	sort(timers.begin(),last_it,TimerEntryPtrCmp()); //re-sort the timers we're processing (at the beginning of timers)
 	inplace_merge(timers.begin(),last_it,timers.end(),TimerEntryPtrCmp()); //now do a merge of the sorted processed stuff and the rest of the list (which is still sorted)
 	//	if(process.size()>0) chkTimers();
-	for(timer_it_t it=process.begin(); it!=process.end(); it++) // process the timers we say we're going to, can no longer assume anything about the state of the world
-		(*it)->el->processEvent(EventBase(EventBase::timerEGID,(*it)->sid,EventBase::statusETID,(*it)->next));
+	for(timer_it_t it=process.begin(); it!=process.end(); it++) { // process the timers we say we're going to, can no longer assume anything about the state of the world
+		EventBase e(EventBase::timerEGID,(*it)->sid,EventBase::statusETID,(*it)->next);
+		try {
+			(*it)->el->processEvent(e);
+		} catch(const std::exception& ex) {
+			std::string msg="Occurred while processing event "+e.getName()+" by ";
+			if(BehaviorBase * beh=dynamic_cast<BehaviorBase*>((*it)->el))
+				msg+="listener "+beh->getName();
+			else
+				msg+="unnamed EventListener";
+			if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),&ex))
+				throw;
+		} catch(...) {
+			std::string msg="Occurred while processing event "+e.getName()+" by ";
+			if(BehaviorBase * beh=dynamic_cast<BehaviorBase*>((*it)->el))
+				msg+="listener "+beh->getName();
+			else
+				msg+="unnamed EventListener";
+			if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),NULL))
+				throw;
+		}
+	}
 	//	if(process.size()>0) chkTimers();
 	static const TimerEntry deadTimer((unsigned int)-1); // matches all the dead ones as set in the incrementation phase
 	last_it=lower_bound(timers.begin(),timers.end(),&deadTimer,TimerEntryPtrCmp()); //find the beginning of all the non-repeating timers we're clearing
@@ -345,14 +367,52 @@
 	std::vector<EventTrapper*> t;
 	trappers.getMapping(e,t);
 	for(std::vector<EventTrapper*>::iterator it=t.begin(); it!=t.end(); it++)
-		if(trappers.verifyMapping(*it,e))
-			if((*it)->trapEvent(e))
-				return;
+		if(trappers.verifyMapping(*it,e)) {
+			try {
+				if((*it)->trapEvent(e))
+					return;
+			} catch(const std::exception& ex) {
+				std::string msg="Occurred while processing event "+e.getName()+" by ";
+				if(BehaviorBase * beh=dynamic_cast<BehaviorBase*>(*it))
+					msg+="trapper "+beh->getName();
+				else
+					msg+="unnamed EventTrapper";
+				if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),&ex))
+					throw;
+			} catch(...) {
+				std::string msg="Occurred while processing event "+e.getName()+" by ";
+				if(BehaviorBase * beh=dynamic_cast<BehaviorBase*>(*it))
+					msg+="trapper "+beh->getName();
+				else
+					msg+="unnamed EventTrapper";
+				if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),NULL))
+					throw;
+			}
+		}
 	std::vector<EventListener*> l;
 	listeners.getMapping(e,l);
 	for(std::vector<EventListener*>::iterator it=l.begin(); it!=l.end(); it++)
-		if(listeners.verifyMapping(*it,e))
-			(*it)->processEvent(e);
+		if(listeners.verifyMapping(*it,e)) {
+			try {
+				(*it)->processEvent(e);
+			} catch(const std::exception& ex) {
+				std::string msg="Occurred while processing event "+e.getName()+" by ";
+				if(BehaviorBase * beh=dynamic_cast<BehaviorBase*>(*it))
+					msg+="listener "+beh->getName();
+				else
+					msg+="unnamed EventListener";
+				if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),&ex))
+					throw;
+			} catch(...) {
+				std::string msg="Occurred while processing event "+e.getName()+" by ";
+				if(BehaviorBase * beh=dynamic_cast<BehaviorBase*>(*it))
+					msg+="listener "+beh->getName();
+				else
+					msg+="unnamed EventListener";
+				if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),NULL))
+					throw;
+			}
+		}
 	//	cout << "done." << flush;
 }
 
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/Shared/ProjectInterface.cc ./Shared/ProjectInterface.cc
--- ../Tekkotsu_2.4/Shared/ProjectInterface.cc	Wed Jun  1 01:47:49 2005
+++ ./Shared/ProjectInterface.cc	Tue Aug 16 14:00:17 2005
@@ -1,37 +1,63 @@
 #include "ProjectInterface.h"
-#include "Events/VisionObjectEvent.h"
+#include "Wireless/Socket.h"
+#include <exception>
 
-FilterBankGenerator * ProjectInterface::defRawCameraGenerator=0;
-FilterBankGenerator * ProjectInterface::defInterleavedYUVGenerator=0;
-JPEGGenerator * ProjectInterface::defColorJPEGGenerator=0;
-JPEGGenerator * ProjectInterface::defGrayscaleJPEGGenerator=0;
-SegmentedColorGenerator * ProjectInterface::defSegmentedColorGenerator=0;
-RLEGenerator * ProjectInterface::defRLEGenerator=0;
-RegionGenerator * ProjectInterface::defRegionGenerator=0;
+namespace ProjectInterface {
 
-unsigned int ProjectInterface::visRawCameraSID=0;
+	bool displayException(const char * file, int line, const char * message, const std::exception* ex) {
+		if(file!=NULL) {
+			serr->printf("Exception caught at %s:%d => ",file,line);
+		} else {
+			serr->printf("Exception => ");
+		}
+		if(ex!=NULL) {
+			serr->printf("'%s'",ex->what());
+		} else {
+			serr->printf("'%s'","Unknown type");
+		}
+		if(message!=NULL) {
+			serr->printf(" (%s)\n",message);
+		} else {
+			serr->printf("\n");
+		}
+		return true;
+	}
+	bool (*uncaughtException)(const char * file, int line, const char * message, const std::exception* ex)=&displayException;
 
-unsigned int ProjectInterface::visInterleaveSID=0;
 
-unsigned int ProjectInterface::visColorJPEGSID=0;
-unsigned int ProjectInterface::visGrayscaleJPEGSID=1;
+	FilterBankGenerator * defRawCameraGenerator=0;
+	FilterBankGenerator * defInterleavedYUVGenerator=0;
+	JPEGGenerator * defColorJPEGGenerator=0;
+	JPEGGenerator * defGrayscaleJPEGGenerator=0;
+	SegmentedColorGenerator * defSegmentedColorGenerator=0;
+	RLEGenerator * defRLEGenerator=0;
+	RegionGenerator * defRegionGenerator=0;
 
-unsigned int ProjectInterface::visSegmentSID=0;
+	unsigned int visRawCameraSID=0;
 
-unsigned int ProjectInterface::visRLESID=0;
+	unsigned int visInterleaveSID=0;
 
-unsigned int ProjectInterface::visRegionSID=0;
+	unsigned int visColorJPEGSID=0;
+	unsigned int visGrayscaleJPEGSID=1;
 
-unsigned int ProjectInterface::visPinkBallSID=0;
-unsigned int ProjectInterface::visBlueBallSID=1;
-unsigned int ProjectInterface::visHandSID=2;
+	unsigned int visSegmentSID=0;
 
-unsigned int ProjectInterface::doubleLayer=5;
-unsigned int ProjectInterface::fullLayer=4;
-unsigned int ProjectInterface::halfLayer=3;
-unsigned int ProjectInterface::quarterLayer=2;
-unsigned int ProjectInterface::eighthLayer=1;
-unsigned int ProjectInterface::sixteenthLayer=0;
+	unsigned int visRLESID=0;
+
+	unsigned int visRegionSID=0;
+
+	unsigned int visPinkBallSID=0;
+	unsigned int visBlueBallSID=1;
+	unsigned int visHandSID=2;
+
+	unsigned int doubleLayer=5;
+	unsigned int fullLayer=4;
+	unsigned int halfLayer=3;
+	unsigned int quarterLayer=2;
+	unsigned int eighthLayer=1;
+	unsigned int sixteenthLayer=0;
+
+}
 
 /*! @file
  * @brief Provides instantiation of the non-required members of ProjectInterface
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/Shared/ProjectInterface.h ./Shared/ProjectInterface.h
--- ../Tekkotsu_2.4/Shared/ProjectInterface.h	Wed Jun  1 01:47:49 2005
+++ ./Shared/ProjectInterface.h	Tue Aug 16 14:00:17 2005
@@ -8,6 +8,9 @@
 class RLEGenerator;
 class RegionGenerator;
 class JPEGGenerator;
+namespace std {
+	class exception;
+}
 
 //! A collection of the global variables which should be set by a project to use the Tekkotsu framework
 /*! You don't necessarily need to define all of these, but if you want
@@ -39,6 +42,27 @@
 	 *  (Each call should return the same behavior) */
 	BehaviorBase& startupBehavior();
 
+	//! The exception handler for exceptions which have fallen through to base Tekkotsu functions
+	/*! You can override this to install your own handler by assigning a
+	 *  new function.  This defaults to displayException(), which
+	 *  <b>does not</b> call abort() (which would otherwise be the
+	 *  default if the exception fell through).
+	 *  @param file The file where the exception was caught (usually just pass __FILE__), or NULL
+	 *  @param line The line number where the exception was caught (usually just pass __LINE__), if @a file is NULL, @a line is ignored
+	 *  @param message An addition message, or NULL
+	 *  @param ex The exception which was caught, or NULL if it is was not a std::exception subclass
+	 *  @return true if the exception was handled, false if the exception should be rethrown */
+	extern bool (*uncaughtException)(const char * file, int line, const char * message, const std::exception* ex);
+
+	//! Displays information about an exception on #serr, provides a default value for #uncaughtException
+	/*! You can call this directly from your own code any time you would like an exception error message.
+	 *  @param file The file where the exception was caught (usually just pass __FILE__), or NULL
+	 *  @param line The line number where the exception was caught (usually just pass __LINE__), if @a file is NULL, @a line is ignored
+	 *  @param message An addition message, or NULL
+	 *  @param ex The exception which was caught, or NULL if it is was not a std::exception subclass
+	 *  @return true, indicating the exception was handled adequately */
+	bool displayException(const char * file, int line, const char * message, const std::exception* ex);
+
 	//! A collection of the various stages of vision processing.  None of these are absolutely required, but are needed to run included demo behaviors and TekkotsuMon modules
 	/*! @name Vision Setup */
 	//! pointer to generator
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/Shared/debuget.h ./Shared/debuget.h
--- ../Tekkotsu_2.4/Shared/debuget.h	Sun Aug  7 00:11:04 2005
+++ ./Shared/debuget.h	Tue Aug 16 17:23:43 2005
@@ -2,6 +2,7 @@
 #define INCLUDED_debuget_h
 
 #include <stdio.h>
+#include <ctype.h>
 
 #ifdef DEBUG
 #include <iostream>
@@ -101,8 +102,6 @@
 	}
 }
 
-#include <ctype.h>
-
 //! displays hex and ascii values of @a size bytes from @a p
 inline void hexout3(const char* buf, size_t size) {
 	const unsigned int linelen=24;
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/Vision/BufferedImageGenerator.cc ./Vision/BufferedImageGenerator.cc
--- ../Tekkotsu_2.4/Vision/BufferedImageGenerator.cc	Fri Aug  5 17:56:21 2005
+++ ./Vision/BufferedImageGenerator.cc	Mon Aug 15 19:19:01 2005
@@ -243,8 +243,8 @@
 
 void BufferedImageGenerator::freeCaches() {
 	FilterBankGenerator::freeCaches();
-	for(unsigned int i=0; i<numChannels; i++)
-		for(unsigned int j=0; j<numLayers; j++)
+	for(unsigned int i=0; i<numLayers; i++)
+		for(unsigned int j=0; j<numChannels; j++)
 			isAllocated[i][j]=false;
 }
 
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/Vision/InterleavedYUVGenerator.cc ./Vision/InterleavedYUVGenerator.cc
--- ../Tekkotsu_2.4/Vision/InterleavedYUVGenerator.cc	Fri Aug  5 17:56:04 2005
+++ ./Vision/InterleavedYUVGenerator.cc	Mon Aug 15 18:57:16 2005
@@ -117,8 +117,8 @@
 }
 
 void
-InterleavedYUVGenerator::setNumImages(unsigned int nLayers, unsigned int nChannels) {
-	if(nLayers==numLayers && nChannels==numChannels)
+InterleavedYUVGenerator::setNumImages(unsigned int nLayers, unsigned int /*nChannels*/) {
+	if(nLayers==numLayers && 1==numChannels) // this generator only has 1 channel
 		return;
 	FilterBankGenerator::setNumImages(nLayers,1);
 	isAllocated=new bool*[numLayers];
@@ -133,8 +133,8 @@
 void
 InterleavedYUVGenerator::freeCaches() {
 	FilterBankGenerator::freeCaches();
-	for(unsigned int i=0; i<numChannels; i++)
-		for(unsigned int j=0; j<numLayers; j++)
+	for(unsigned int i=0; i<numLayers; i++)
+		for(unsigned int j=0; j<numChannels; j++)
 			isAllocated[i][j]=false;
 }
 
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/Vision/JPEGGenerator.cc ./Vision/JPEGGenerator.cc
--- ../Tekkotsu_2.4/Vision/JPEGGenerator.cc	Mon Jun 13 15:39:33 2005
+++ ./Vision/JPEGGenerator.cc	Tue Aug 16 14:08:51 2005
@@ -199,7 +199,7 @@
 void
 JPEGGenerator::calcImage(unsigned int layer, unsigned int chan) {
 	PROFSECTION("JPEGGenerator::calcImage(...)",state->mainProfile);
-
+try {
 	//pass the destination buffer and buffer size here
 	jpeg_mem_dest(&cinfo, images[layer][chan], widths[layer]*heights[layer]*3+JPEG_HEADER_PAD);
 
@@ -274,6 +274,13 @@
 	// results
 	bytesUsed[layer][chan]=jpeg_mem_size(&cinfo);
 	imageValids[layer][chan]=true;
+} catch(const std::exception& ex) {
+	std::cerr << "Exception while compressing JPEG: " << ex.what() << std::endl; //really, can only be bad_alloc
+	std::cerr << "layer==" << layer << " channel==" << chan << " image==" << (void*)images[layer][chan] << std::endl;
+	std::cerr << "width==" << widths[layer] << " height==" << heights[layer] << std::endl;
+	std::cerr << "row_stride==" << src->getStride(layer) << " next_scanline==" << (void*)cinfo.next_scanline << " image_height==" << cinfo.image_height << std::endl;
+	jpeg_destroy_compress(&cinfo);
+}
 }
 
 void
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/Wireless/Wireless.cc ./Wireless/Wireless.cc
--- ../Tekkotsu_2.4/Wireless/Wireless.cc	Mon Aug  1 19:17:59 2005
+++ ./Wireless/Wireless.cc	Tue Aug 16 14:37:05 2005
@@ -1,6 +1,7 @@
 #include "Wireless.h"
 #include "Socket.h"
 #include <cstring>
+#include "Shared/ProjectInterface.h"
 
 Wireless *wireless=NULL;
 
@@ -184,6 +185,7 @@
 void
 Wireless::ListenCont(void* msg)
 {
+try {
 	antEnvMsg * Msg = ( antEnvMsg * ) msg;
 	int sock = ( int )( Msg->continuation );
 
@@ -206,11 +208,20 @@
 			//cout << "Listen set lip: " << local_ipaddr << endl;
 			receive( sock );
 		}
+
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Listen callback",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Listen callback",NULL))
+		throw;
+}
 }
 
 void
 Wireless::ConnectCont(void *msg)
 {
+try {
 	antEnvMsg * Msg = ( antEnvMsg * ) msg;
 	int sock = ( int )( Msg->continuation );
 
@@ -228,11 +239,20 @@
 			//cout << "Connect set lip: " << local_ipaddr << endl;
 			receive( sock );
 		}
+
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Connect callback",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Connect callback",NULL))
+		throw;
+}
 }
 
 void
 Wireless::BindCont(void *msg)
 {
+try {
 	UDPEndpointBindMsg* bindMsg = (UDPEndpointBindMsg*)msg;
 	int sock = (int)bindMsg->continuation;
 
@@ -248,6 +268,14 @@
 	} else {
 		//cout << "Bind got 0" << endl;
 		}*/
+
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Bind callback",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Bind callback",NULL))
+		throw;
+}
 }
 
 void
@@ -282,6 +310,7 @@
 void
 Wireless::SendCont(void* msg)
 {
+try {
 	antEnvMsg * Msg = ( antEnvMsg * ) msg;
 	int sock = ( int )( Msg->continuation );
 
@@ -310,6 +339,14 @@
 		}
 
 	sockets[sock]->flush();
+
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Send callback",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Send callback",NULL))
+		throw;
+}
 }
 
 /*! @bug This doesn't actually seem to block until the message is
@@ -397,6 +434,7 @@
 void
 Wireless::ReceiveCont(void* msg)
 {
+try {
 	// get the socket index before casting the message into UDP or TCP form
 	antEnvMsg * Msg = ( antEnvMsg * ) msg;
 	int sock = ( int )( Msg->continuation );
@@ -460,6 +498,14 @@
 		}
 
 	receive( sock );
+
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Receive callback",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Receive callback",NULL))
+		throw;
+}
 }
 
 void
@@ -522,6 +568,7 @@
 void
 Wireless::CloseCont(void* msg)
 {
+try {
 	antEnvMsg * closeMsg = ( antEnvMsg * ) msg;
 	int sock = ( int )( closeMsg->continuation );
 	if ( sockets[sock] == NULL )
@@ -546,6 +593,14 @@
 					break;
 				}
 		}
+
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Close callback",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Wireless Close callback",NULL))
+		throw;
+}
 }
 
 #else // PLATFORM_LOCAL
@@ -944,8 +999,17 @@
 							// clear this message from the receiving buffer
 							if ( sockets[*it]->state != CONNECTION_CONNECTED )
 								connect( *it, sockets[*it]->getPeerAddressAsString().c_str(), sockets[*it]->getPeerPort() );
-						} else if ( sockets[*it]->rcvcbckfn != NULL )
-							sockets[*it]->rcvcbckfn( ( char * ) sockets[*it]->recvData, sockets[*it]->recvSize );
+						} else if ( sockets[*it]->rcvcbckfn != NULL ) {
+							try {
+								sockets[*it]->rcvcbckfn( ( char * ) sockets[*it]->recvData, sockets[*it]->recvSize );
+							} catch(const std::exception& ex) {
+								if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during networking received data callback",&ex))
+									throw;
+							} catch(...) {
+								if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during networking received data callback",NULL))
+									throw;
+							}
+						}
 						sockets[*it]->recvSize = 0;
 					}
 				}
@@ -971,8 +1035,17 @@
 					continue;
 				} else {
 					//cout << "Read " << sockets[*it]->recvSize << " bytes " << sockets[*it]->rcvcbckfn << endl;
-					if ( sockets[*it]->rcvcbckfn != NULL )
-						sockets[*it]->rcvcbckfn( ( char * ) sockets[*it]->recvData, sockets[*it]->recvSize );
+					if ( sockets[*it]->rcvcbckfn != NULL ) {
+						try {
+							sockets[*it]->rcvcbckfn( ( char * ) sockets[*it]->recvData, sockets[*it]->recvSize );
+						} catch(const std::exception& ex) {
+							if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during networking received data callback",&ex))
+								throw;
+						} catch(...) {
+							if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during networking received data callback",NULL))
+								throw;
+						}
+					}
 					sockets[*it]->recvSize = 0;
 				}
 			} else {
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/aperios/MMCombo/MMCombo.cc ./aperios/MMCombo/MMCombo.cc
--- ../Tekkotsu_2.4/aperios/MMCombo/MMCombo.cc	Thu Aug  4 17:10:11 2005
+++ ./aperios/MMCombo/MMCombo.cc	Tue Aug 16 14:27:58 2005
@@ -38,6 +38,7 @@
 		soundManagerMemRgn(NULL),
 		runLevel(0), num_open(0), etrans(NULL), isStopped(true)
 {
+try {
 	for(unsigned int i=0; i<NumOutputs; i++) {
 		primIDs[i]=oprimitiveID_UNDEF;
 		open[i]=false;
@@ -48,12 +49,20 @@
 	EventTranslator::registerPrototype<LocomotionEvent>();
 	EventTranslator::registerPrototype<TextMsgEvent>();
 	EventTranslator::registerPrototype<VisionObjectEvent>();
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MMCombo construction",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MMCombo construction",NULL))
+		throw;
+}
 }
 
 
 OStatus
 MMCombo::DoInit(const OSystemEvent&)
 {
+try {
 	cout << objectName << "::DoInit() " << endl;
 
 	isStopped=false;
@@ -161,11 +170,21 @@
 
 	cout << objectName << "::DoInit()-DONE" << endl;
 	return oSUCCESS;
+
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MMCombo::DoInit()",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MMCombo::DoInit()",NULL))
+		throw;
+}
+return oSUCCESS;
 }
 
 OStatus
 MMCombo::DoStart(const OSystemEvent&)
 {
+try {
 	cout << objectName << "::DoStart() " << endl;
 
 	// initialize the current power status, doesn't always give us
@@ -192,11 +211,21 @@
 	
 	cout << objectName << "::DoStart()-DONE" << endl;
 	return oSUCCESS;
+
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MMCombo::DoStart()",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MMCombo::DoStart()",NULL))
+		throw;
+}
+return oSUCCESS;
 }
 
 OStatus
 MMCombo::DoStop(const OSystemEvent&)
 {
+try {
 	cout << objectName << "::DoStop()..." << endl;
 	if(strcmp(objectName,"MainObj")==0) {
 		ProjectInterface::startupBehavior().DoStop();
@@ -208,11 +237,21 @@
 	isStopped=true;
 	cout << objectName << "::DoStop()-DONE" << endl;
 	return oSUCCESS;
+
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MMCombo::DoStop()",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MMCombo::DoStop()",NULL))
+		throw;
+}
+return oSUCCESS;
 }
 
 OStatus
 MMCombo::DoDestroy(const OSystemEvent&)
 {
+try {
 	cout << objectName << "::DoDestroy()..." << endl;
 	delete etrans;
 	etrans=NULL;
@@ -228,6 +267,15 @@
 	DELETE_ALL_SUBJECT_AND_OBSERVER;
 	cout << objectName << "::DoDestroy()-DONE" << endl;
 	return oSUCCESS;
+
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MMCombo::DoDestroy()",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during MMCombo::DoDestroy()",NULL))
+		throw;
+}
+return oSUCCESS;
 }
 
 /*! Called when MotoObj is initially ready as well as when it has finished
@@ -298,6 +346,8 @@
 
 void
 MMCombo::GotInterProcessEvent(const ONotifyEvent& event){
+	EventBase* evt=NULL;
+try {
 	//cout << objectName << "-GOTInterProcessEvent " << event.NumOfData() << "..." << flush;
 	//cout << TimeET() << endl;
 	//	PROFSECTION("GotMemRegion()",state->mainProfile);
@@ -305,17 +355,34 @@
 		return;
 	for(int i=0; i<event.NumOfData(); i++) {
 		RCRegion * msg = event.RCData(i);
-		EventBase* evt=etrans->decodeEvent(msg->Base(),msg->Size());
+		evt=etrans->decodeEvent(msg->Base(),msg->Size());
 		if(evt!=NULL)
 			erouter->postEvent(evt);
 	}
   observer[obsEventTranslatorComm]->AssertReady();
 	//cout << "done" << endl;
+
+} catch(const std::exception& ex) {
+  observer[obsEventTranslatorComm]->AssertReady();
+	std::string msg("Occurred during inter-process event processing");
+	if(evt!=NULL)
+		msg+=": "+evt->getName();
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),&ex))
+		throw;
+} catch(...) {
+  observer[obsEventTranslatorComm]->AssertReady();
+	std::string msg("Occurred during inter-process event processing");
+	if(evt!=NULL)
+		msg+=": "+evt->getName();
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,msg.c_str(),NULL))
+		throw;
+}
 }
 
 		
 void
 MMCombo::ReadySendJoints(const OReadyEvent& sysevent) {
+try {
 
 	if(isStopped) {
 		//cout << "BAH!ReadySendJoints" << endl;
@@ -472,10 +539,28 @@
 		ReadySendJoints(sysevent);
 	} else //recursive base case
 		subject[sbjMoveJoint]->NotifyObservers();
+
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during joint angle updates",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during joint angle updates",NULL))
+		throw;
+}
 }
 
 void
 MMCombo::GotSensorFrame(const ONotifyEvent& event){
+try {
+	erouter->processTimers();
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",NULL))
+		throw;
+}
+try {
 	//	if(state && state->buttons[RFrPawOffset])
 	//	cout << "SENSOR..."<<flush;
 	if(isStopped) {
@@ -487,7 +572,6 @@
 
   OSensorFrameVectorData* rawsensor = reinterpret_cast<OSensorFrameVectorData*>(event.RCData(0)->Base());
 	state->read(rawsensor[0],erouter);
-	erouter->processTimers();
 	static unsigned int throwaway=1; //i thought the first few sensor updates might be flakey, but now i think not.  But a good way to delay startup.
 	if(throwaway!=0) {
 		throwaway--;
@@ -518,6 +602,16 @@
   observer[obsSensorFrame]->AssertReady();
 	//	if(state && state->buttons[RFrPawOffset])
 	//	cout << "done" << endl;
+
+} catch(const std::exception& ex) {
+  observer[obsSensorFrame]->AssertReady();
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during sensor update processing",&ex))
+		throw;
+} catch(...) {
+  observer[obsSensorFrame]->AssertReady();
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during sensor update processing",NULL))
+		throw;
+}
 }
 
 void
@@ -527,9 +621,17 @@
 		return;
 	}
 
+try {
+	erouter->processTimers();
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",NULL))
+		throw;
+}
+try {
 	PROFSECTION("GotImage()",state->mainProfile);
-
-  erouter->processTimers();
   
 	WMvari(int, frame_counter, 0);
 	++frame_counter;
@@ -538,13 +640,31 @@
 	erouter->postEvent(new DataEvent<const OFbkImageVectorData*>(reinterpret_cast<const OFbkImageVectorData*>(event.Data(0)),EventBase::visOFbkEGID,0,EventBase::statusETID));
 	erouter->postEvent(new DataEvent<const OFbkImageVectorData*>(reinterpret_cast<const OFbkImageVectorData*>(event.Data(0)),EventBase::visOFbkEGID,0,EventBase::deactivateETID));
 	
-  erouter->processTimers();
-  
   observer[obsImage]->AssertReady();
+
+} catch(const std::exception& ex) {
+  observer[obsImage]->AssertReady();
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during camera image processing",&ex))
+		throw;
+} catch(...) {
+  observer[obsImage]->AssertReady();
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during camera image processing",NULL))
+		throw;
+}
+try {
+	erouter->processTimers();
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",NULL))
+		throw;
+}
 }
 
 void
 MMCombo::GotAudio(const ONotifyEvent& event){
+try {
 	if(isStopped) {
 		//cout << "BAH!GotAudio" << endl;
 		return;
@@ -554,10 +674,28 @@
 
 	for (int i = 0; i < event.NumOfData(); i++) {
 		erouter->postEvent(new DataEvent<const OSoundVectorData*>(reinterpret_cast<const OSoundVectorData*>(event.Data(i)),EventBase::micOSndEGID,0,EventBase::statusETID));
-		erouter->processTimers();
+		try {
+			erouter->processTimers();
+		} catch(const std::exception& ex) {
+			if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",&ex))
+				throw;
+		} catch(...) {
+			if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",NULL))
+				throw;
+		}
 	}
   
   observer[obsMic]->AssertReady();
+
+} catch(const std::exception& ex) {
+  observer[obsMic]->AssertReady();
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during audio processing",&ex))
+		throw;
+} catch(...) {
+  observer[obsMic]->AssertReady();
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during audio processing",NULL))
+		throw;
+}
 }
 
 void
@@ -566,6 +704,16 @@
 		//cout << "BAH!GotPowerEvent" << endl;
 		return;
 	}
+try {
+	erouter->processTimers();
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during timer processing",NULL))
+		throw;
+}
+try {
 
 	//	cout << "POWER..."<<flush;
 	PROFSECTION("PowerEvent()",state->mainProfile);
@@ -577,7 +725,6 @@
 	}
 	const OPowerStatus* result = &static_cast<OPowerStatusMessage*>(msg)->powerStatus;
 	state->read(*result,erouter);
-	erouter->processTimers();
 	// this part watches to see if the power button is pressed to shutdown the robot
 	// i'm leaving this low-level because there's not much else you can do anyway...
 	// the hardware kills power to the motors, and as far as we can tell, you can't
@@ -588,6 +735,14 @@
 		OPENR::Shutdown(bc);
 	}
 	//	cout << "done" << endl;
+
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during power status update",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during power status update",NULL))
+		throw;
+}
 }
 
 void
@@ -748,9 +903,17 @@
 MMCombo::addRunLevel() {
 	runLevel++;
 	if(runLevel==readyLevel) {
-		cout << "START UP BEHAVIOR..." << flush;
-		ProjectInterface::startupBehavior().DoStart();
-		cout << "START UP BEHAVIOR-DONE" << endl;
+		try {
+			cout << "START UP BEHAVIOR..." << flush;
+			ProjectInterface::startupBehavior().DoStart();
+			cout << "START UP BEHAVIOR-DONE" << endl;
+		} catch(const std::exception& ex) {
+			if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during StartupBehavior construction and startup",&ex))
+				throw;
+		} catch(...) {
+			if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during StartupBehavior construction and startup",NULL))
+				throw;
+		}
 	}
 }
 
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/docs/doxygencfg ./docs/doxygencfg
--- ../Tekkotsu_2.4/docs/doxygencfg	Sun Aug  7 00:11:04 2005
+++ ./docs/doxygencfg	Tue Aug 16 14:57:19 2005
@@ -23,7 +23,7 @@
 # This could be handy for archiving the generated documentation or 
 # if some version control system is used.
 
-PROJECT_NUMBER         = 2.4
+PROJECT_NUMBER         = 2.4.1
 
 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
 # base path where the generated documentation will be put. 
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/docs/doxygenhead.html ./docs/doxygenhead.html
--- ../Tekkotsu_2.4/docs/doxygenhead.html	Tue Jul 19 19:35:22 2005
+++ ./docs/doxygenhead.html	Fri Aug 12 14:51:53 2005
@@ -25,15 +25,15 @@
 					<!-- #Bar# --> <td style="vertical-align: top; background-color: rgb(0, 0, 0);"><br></td>
 					<!-- #Downloads# --> <td style="vertical-align: top;"><a target="_top" href="../downloads.html">Downloads</a></td>
 					<!-- #Bar# --> <td style="vertical-align: top; background-color: rgb(0, 0, 0);"><br></td>
-					<!-- #Tutorials# --> <td style="vertical-align: top;"><a target="_top" href="../development.html">Tutorials</a></td>
+					<!-- #Tutorials# --> <td style="vertical-align: top;"><a target="_top" href="../development.html">Dev. Resources</a></td>
 					<!-- #Bar# --> <td style="vertical-align: top; background-color: rgb(0, 0, 0);"><br></td>
 					<!-- #Current# --><!-- #Reference# --> <td style="vertical-align: top;"><i>Reference</i></td>
 					<!-- #Bar# --> <td style="vertical-align: top; background-color: rgb(0, 0, 0);"><br></td>
-					<!-- #Credits# --> <td style="vertical-align: top;"><a target="_top" href="../acknowledgements.html">Credits</a> </td>
+					<!-- #Credits# --> <td style="vertical-align: top;"><a target="_top" href="../acknowledgments.html">Credits</a> </td>
 				</tr>
 			</tbody>
 		</table>
-<table style="text-align: left; margin-left: auto; margin-right: auto; width: 700px;" border="0" cellspacing="2" cellpadding="2">
+<table style="text-align: left; margin-left: auto; margin-right: auto; width: 750px;" border="0" cellspacing="2" cellpadding="2">
   <tbody>
     <tr>
       <td style="vertical-align: top;">
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/docs/html/index.html ./docs/html/index.html
--- ../Tekkotsu_2.4/docs/html/index.html	Sun Aug  7 00:11:04 2005
+++ ./docs/html/index.html	Fri Aug 12 14:52:52 2005
@@ -36,7 +36,7 @@
  style="vertical-align: top; background-color: rgb(0, 0, 0);"><br>
       </td>
 <!-- #Tutorials# --> <td style="vertical-align: top;"><a
- href="../development.html" target="_top">Tutorials</a></td>
+ href="../development.html" target="_top">Dev. Resources</a></td>
 <!-- #Bar# --> <td
  style="vertical-align: top; background-color: rgb(0, 0, 0);"><br>
       </td>
@@ -46,7 +46,7 @@
  style="vertical-align: top; background-color: rgb(0, 0, 0);"><br>
       </td>
 <!-- #Credits# --> <td style="vertical-align: top;"><a
- href="../acknowledgements.html" target="_top">Credits</a> </td>
+ href="../acknowledgments.html" target="_top">Credits</a> </td>
     </tr>
   </tbody>
 </table>
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/local/sim/Main.cc ./local/sim/Main.cc
--- ../Tekkotsu_2.4/local/sim/Main.cc	Wed Jul  6 18:53:10 2005
+++ ./local/sim/Main.cc	Tue Aug 16 14:24:43 2005
@@ -64,6 +64,8 @@
 
 
 void Main::DoStart() {
+try {
+
 	Process::DoStart();
 	//These are constructed by other processes, so need to wait
 	//until the construction runlevel is complete
@@ -75,9 +77,19 @@
 	wireless_thread.start();
 	evtrecv=new MessageReceiver(*events,gotEvent,false);
 	visrecv=new MessageReceiver(*cameraFrames,gotCamera,false);
+
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Main DoStart",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Main DoStart",NULL))
+		throw;
+}
 }
 
 void Main::run() {
+try {
+
 	ProjectInterface::startupBehavior().DoStart();
 
 	evtrecv->start();
@@ -89,9 +101,19 @@
 	evtrecv->finish();
 
 	ProjectInterface::startupBehavior().DoStop();
+
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Main 'run' runlevel (startupBehavior initialization and startup)",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Main 'run' runlevel (startupBehavior initialization and startup)",NULL))
+		throw;
+}
 }
 
 void Main::DoStop() {
+try {
+
 	events->close();
 
 	delete visrecv;
@@ -115,6 +137,14 @@
 		curimg->RemoveReference();
 
 	Process::DoStop();
+
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Main DoStop",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during Main DoStop",NULL))
+		throw;
+}
 }
 
 bool Main::canManuallyAdvance() {
@@ -164,6 +194,7 @@
 
 
 bool Main::gotCamera(RCRegion* msg) {
+try {
 	if(msg==NULL)
 		return true;
 	msg->AddReference();
@@ -184,16 +215,39 @@
 	erouter->postEvent(new DataEvent<BufferedImageGenerator::ImageSource>(img,EventBase::visOFbkEGID,0,EventBase::statusETID));
 	erouter->postEvent(new DataEvent<BufferedImageGenerator::ImageSource>(img,EventBase::visOFbkEGID,0,EventBase::deactivateETID));
 	return isRealtime;
+} catch(const std::exception& ex) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during camera frame processing",&ex))
+		throw;
+} catch(...) {
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,"Occurred during camera frame processing",NULL))
+		throw;
+}
+return true;
 }
 
 bool Main::gotEvent(RCRegion* msg) {
-	EventBase* evt=EventTranslator::decodeEvent(msg->Base(),msg->Size());
+EventBase* evt=NULL;
+try {
+	evt=EventTranslator::decodeEvent(msg->Base(),msg->Size());
 	if(evt==NULL) {
 		cerr << "ERROR: Main::gotEvent() failed to decode message" << endl;
 		return true;
 	}
 	erouter->postEvent(evt);
-	return true;
+} catch(const std::exception& ex) {
+	std::string emsg("Occurred during inter-process event processing");
+	if(evt!=NULL)
+		emsg+=": "+evt->getName();
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,emsg.c_str(),&ex))
+		throw;
+} catch(...) {
+	std::string emsg("Occurred during inter-process event processing");
+	if(evt!=NULL)
+		emsg+=": "+evt->getName();
+	if(!ProjectInterface::uncaughtException(__FILE__,__LINE__,emsg.c_str(),NULL))
+		throw;
+}
+return true;
 }
 
 /*! @file
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/Makefile ./tools/Makefile
--- ../Tekkotsu_2.4/tools/Makefile	Tue Aug  9 21:58:36 2005
+++ ./tools/Makefile	Tue Aug 16 17:11:04 2005
@@ -17,10 +17,14 @@
 		printf "Checking tool $$dir:\n"; \
 		$(MAKE) -C "$$dir" clean; \
 		if [ $$? -ne 0 ] ; then \
-			exit $$?; \
+			exit 1; \
 		fi; \
-		$(MAKE) -C "$$dir" all; \
+		$(MAKE) -C "$$dir"; \
 		if [ $$? -ne 0 ] ; then \
-			exit $$?; \
+			exit 1; \
+		fi; \
+		$(MAKE) -C "$$dir" test; \
+		if [ $$? -ne 0 ] ; then \
+			exit 1; \
 		fi; \
 	done
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/binstrswap/Makefile ./tools/binstrswap/Makefile
--- ../Tekkotsu_2.4/tools/binstrswap/Makefile	Sun Aug 24 17:19:21 2003
+++ ./tools/binstrswap/Makefile	Tue Aug 16 16:47:42 2005
@@ -1,4 +1,4 @@
-.PHONY: all clean
+.PHONY: all clean test
 
 all: binstrswap
 
@@ -7,4 +7,6 @@
 
 clean:
 	rm -f binstrswap
+
+test:
 
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/easytrain/Makefile ./tools/easytrain/Makefile
--- ../Tekkotsu_2.4/tools/easytrain/Makefile	Thu Aug  4 16:58:05 2005
+++ ./tools/easytrain/Makefile	Tue Aug 16 16:48:09 2005
@@ -9,7 +9,7 @@
 SEP:=$(shell if [ "`uname`" = "CYGWIN" -o "`uname`" \> "CYGWIN" -a "`uname`" \< "CYGWIO" ] ; then echo ";" ; else echo ":" ; fi )
 CXXFLAGS=-deprecation -classpath ".$(SEP)../mon/ftp.jar"
 
-.PHONY: all clean msg build clearbuildlist
+.PHONY: all clean msg build clearbuildlist test
 
 all: clearbuildlist build
 
@@ -33,3 +33,6 @@
 
 clean:
 	rm -f $(OBJS) *~ 
+
+test:
+
Binary files ../Tekkotsu_2.4/tools/easytrain/test2.png and ./tools/easytrain/test2.png differ
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/evenmodtime/Makefile ./tools/evenmodtime/Makefile
--- ../Tekkotsu_2.4/tools/evenmodtime/Makefile	Sun Aug 24 17:19:27 2003
+++ ./tools/evenmodtime/Makefile	Tue Aug 16 16:48:11 2005
@@ -1,4 +1,4 @@
-.PHONY: all clean
+.PHONY: all clean test
 
 all: evenmodtime
 
@@ -7,4 +7,6 @@
 
 clean:
 	rm -f evenmodtime
+
+test:
 
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/filtersyswarn/Makefile ./tools/filtersyswarn/Makefile
--- ../Tekkotsu_2.4/tools/filtersyswarn/Makefile	Sun Aug 24 17:19:32 2003
+++ ./tools/filtersyswarn/Makefile	Tue Aug 16 16:48:15 2005
@@ -1,4 +1,4 @@
-.PHONY: all clean
+.PHONY: all clean test
 
 all: filtersyswarn
 
@@ -7,4 +7,6 @@
 
 clean:
 	rm -f filtersyswarn
+
+test:
 
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/mipaltools/Makefile ./tools/mipaltools/Makefile
--- ../Tekkotsu_2.4/tools/mipaltools/Makefile	Thu Oct  9 15:51:28 2003
+++ ./tools/mipaltools/Makefile	Tue Aug 16 16:48:15 2005
@@ -1,4 +1,4 @@
-.PHONY: all
+.PHONY: all clean test
 
 all: StackedIt
 
@@ -7,3 +7,6 @@
 
 clean:
 	make -C src clean
+
+test:
+
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/mon/Makefile ./tools/mon/Makefile
--- ../Tekkotsu_2.4/tools/mon/Makefile	Thu Mar 31 16:54:08 2005
+++ ./tools/mon/Makefile	Tue Aug 16 16:48:15 2005
@@ -14,7 +14,7 @@
 SEP:=$(shell if [ "`uname`" = "CYGWIN" -o "`uname`" \> "CYGWIN" -a "`uname`" \< "CYGWIO" ] ; then echo ";" ; else echo ":" ; fi )
 CXXFLAGS=-deprecation -classpath ".$(SEP)./ftp.jar$(SEP)./jargs.jar" 
 
-.PHONY: all clean build clearbuildlist
+.PHONY: all clean build clearbuildlist test
 
 all: clearbuildlist build
 
@@ -60,3 +60,6 @@
 	rm -f tmp_buildList.txt "$(AIBO3DCACHE)"
 	find . -name "*.class" -exec rm \{\} \;
 	find . -name "*~" -exec rm \{\} \;
+
+test:
+
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/seg/Makefile ./tools/seg/Makefile
--- ../Tekkotsu_2.4/tools/seg/Makefile	Wed Oct  8 14:26:51 2003
+++ ./tools/seg/Makefile	Tue Aug 16 16:48:15 2005
@@ -9,7 +9,7 @@
 SEP:=$(shell if [ "`uname`" = "CYGWIN" -o "`uname`" \> "CYGWIN" -a "`uname`" \< "CYGWIO" ] ; then echo ";" ; else echo ":" ; fi )
 CXXFLAGS=-deprecation -classpath ".$(SEP)../mon/ftp.jar"
 
-.PHONY: all clean msg build clearbuildlist
+.PHONY: all clean msg build clearbuildlist test
 
 all: clearbuildlist build
 
@@ -33,3 +33,6 @@
 
 clean:
 	rm -f $(OBJS) *~ 
+
+test:
+
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/test/base64/Makefile ./tools/test/base64/Makefile
--- ../Tekkotsu_2.4/tools/test/base64/Makefile	Wed Jun  1 01:48:09 2005
+++ ./tools/test/base64/Makefile	Tue Aug 16 16:13:22 2005
@@ -1,45 +1,49 @@
 
+# This Makefile will handle most aspects of compiling and
+# linking a tool against the Tekkotsu framework.  You probably
+# won't need to make any modifications, but here's the major controls
 
-#if you want to change the target model, it is recommended
-#to set the TEKKOTSU_TARGET_MODEL environment variable
+# Executable name, defaults to:
+#   `basename \`pwd\``-$(TEKKOTSU_TARGET_MODEL)
+TEKKOTSU_TARGET_MODEL?=TGT_ERS7
+BIN:=$(shell pwd | sed 's@.*/@@')-$(shell echo $(patsubst TGT_%,%,$(TEKKOTSU_TARGET_MODEL)))
 
-.PHONY: all tk
+# Build directory
+PROJECT_BUILDDIR:=build
 
-# We use this TK_RT instead of TEKKOTSU_ROOT so things will
-# still work if TEKKOTSU_ROOT is a relative path from some
-# unknown project directory (and thus would be invalid from
-# this subdirectory of 'tools')
-TK_RT:=../../..
+# Source files, defaults to all files ending matching *$(SRCSUFFIX)
+SRCSUFFIX:=.cc
+PROJ_SRC:=$(shell find . -name "*$(SRCSUFFIX)")
 
-TEMPLATE_PROJECT:=$(TK_RT)/project
+# We use a hard-coded TEKKOTSU_ROOT so this tool is always linked against the
+# the framework directory which contains it
+TEKKOTSU_ROOT=../../..
+
+.PHONY: all test
+
+TEMPLATE_PROJECT:=$(TEKKOTSU_ROOT)/project
 TEKKOTSU_ENVIRONMENT_CONFIGURATION?=$(TEMPLATE_PROJECT)/Environment.conf
-$(if $(shell if [ \! -r $(TEKKOTSU_ENVIRONMENT_CONFIGURATION) ] \; then echo failure \; fi),$(error An error has occured, `$(TEKKOTSU_ENVIRONMENT_CONFIGURATION)' could not be found.  You may need to edit TK_RT in the Makefile))
+$(if $(shell if [ \! -r $(TEKKOTSU_ENVIRONMENT_CONFIGURATION) ] \; then echo failure \; fi),$(error An error has occured, `$(TEKKOTSU_ENVIRONMENT_CONFIGURATION)' could not be found.  You may need to edit TEKKOTSU_ROOT in the Makefile))
 
 TEKKOTSU_TARGET_PLATFORM:=PLATFORM_LOCAL
-PROJECT_BUILDDIR:=build
 include $(TEKKOTSU_ENVIRONMENT_CONFIGURATION)
-FILTERSYSWARN:=$(patsubst $(TEKKOTSU_ROOT)/%,$(TK_RT)/%,$(FILTERSYSWARN))
-COLORFILT:=$(patsubst $(TEKKOTSU_ROOT)/%,$(TK_RT)/%,$(COLORFILT))
+FILTERSYSWARN:=$(patsubst $(TEKKOTSU_ROOT)/%,$(TEKKOTSU_ROOT)/%,$(FILTERSYSWARN))
+COLORFILT:=$(patsubst $(TEKKOTSU_ROOT)/%,$(TEKKOTSU_ROOT)/%,$(COLORFILT))
 $(shell mkdir -p $(PROJ_BD))
 
-BIN:=$(shell pwd | sed 's@.*/@@')-$(shell echo $(patsubst TGT_%,%,$(TEKKOTSU_TARGET_MODEL)))
-
-SRCSUFFIX:=.cc
-
-PROJ_SRC:=$(shell find . -name "*$(SRCSUFFIX)")
-
 PROJ_OBJ:=$(patsubst ./%$(SRCSUFFIX),$(PROJ_BD)/%.o,$(PROJ_SRC))
 
 LIBS:= $(TK_BD)/libtekkotsu.a $(TK_BD)/../Motion/roboop/libroboop.a $(TK_BD)/../Shared/newmat/libnewmat.a
 
 DEPENDS:=$(PROJ_OBJ:.o=.d)
 
-CXXFLAGS=-g -Wall -O2 \
-         -I$(TK_RT) \
+CXXFLAGS:=-g -Wall -O2 \
+         -I$(TEKKOTSU_ROOT) \
+         -I../../Shared/jpeg-6b $(shell xml2-config --cflags) \
          -D$(TEKKOTSU_TARGET_PLATFORM) -D$(TEKKOTSU_TARGET_MODEL) 
 
 
-all: tk $(BIN)
+all: $(BIN)
 
 $(BIN): $(PROJ_OBJ) $(LIBS)
 	@echo "Linking $@..."
@@ -49,9 +53,6 @@
 -include $(DEPENDS)
 endif
 
-tk :
-	export TEKKOTSU_TARGET_PLATFORM=PLATFORM_LOCAL; $(MAKE) -C $(TK_RT) compile
-
 %.a :
 	@echo "ERROR: $@ was not found.  You may need to compile the Tekkotsu framework."
 	@echo "Press return to attempt to build it, ctl-C to cancel."
@@ -74,5 +75,17 @@
 	test $$retval -eq 0; \
 
 clean:
-	rm -rf $(BIN) $(PROJECT_BUILDDIR) *~
+	rm -rf $(BIN) $(PROJECT_BUILDDIR) test-* *~
 
+test: $(BIN)
+	./$(BIN) encode binary.gif > test-encoded_b64.txt
+	./$(BIN) decode encoded_b64.txt > test-binary.gif
+	@for x in * ; do \
+		if [ -r "test-$$x" ] ; then \
+			if diff -u "test-$$x" "$$x" ; then \
+				echo "Test '$$x' passed"; \
+			else \
+				echo "Test output '$$x' does not match ideal"; \
+			fi; \
+		fi; \
+	done
\ No newline at end of file
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/test/base64/base64.cc ./tools/test/base64/base64.cc
--- ../Tekkotsu_2.4/tools/test/base64/base64.cc	Wed Jun  1 01:48:09 2005
+++ ./tools/test/base64/base64.cc	Tue Aug 16 15:37:11 2005
@@ -7,6 +7,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/fcntl.h>
+#include <unistd.h>
 
 using namespace std;
 using namespace minisim;
@@ -14,7 +15,7 @@
 int main(int argc, char** argv) {
   initialize();
 
-  if(argc<2 || strcmp(argv[1],"encode") && strcmp(argv[1],"decode")) {
+  if(argc<3 || strcmp(argv[1],"encode") && strcmp(argv[1],"decode")) {
     cerr << "Usage: " << argv[0] << " (encode|decode) filename" << endl;
     exit(2);
   }
@@ -34,7 +35,7 @@
     exit(1);
   }
   unsigned int r=0;
-  while(r<sb.st_size) {
+  while(r<(unsigned int)sb.st_size) {
     unsigned int n=read(fd,buf,sb.st_size-r);
     if(n<=0) {
       cerr << "file load error" << endl;
@@ -48,7 +49,7 @@
   if(isEncode) {
     cout << base64::encode(buf,sb.st_size);
   } else {
-    string enc(buf);
+    string enc(buf,sb.st_size);
     char * dat = base64::decode(enc);
     if(dat==NULL) {
       cerr << "decoding error" << endl;
Binary files ../Tekkotsu_2.4/tools/test/base64/binary.gif and ./tools/test/base64/binary.gif differ
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/test/base64/encoded_b64.txt ./tools/test/base64/encoded_b64.txt
--- ../Tekkotsu_2.4/tools/test/base64/encoded_b64.txt	Wed Dec 31 19:00:00 1969
+++ ./tools/test/base64/encoded_b64.txt	Tue Aug 16 16:13:22 2005
@@ -0,0 +1 @@
+R0lGODlhGgAMAPcAAP//////zP//mf//Zv//M///AP/M///MzP/Mmf/MZv/MM//MAP+Z//+ZzP+Zmf+ZZv+ZM/+ZAP9m//9mzP9mmf9mZv9mM/9mAP8z//8zzP8zmf8zZv8zM/8zAP8A//8AzP8Amf8AZv8AM/8AAMz//8z/zMz/mcz/Zsz/M8z/AMzM/8zMzMzMmczMZszMM8zMAMyZ/8yZzMyZmcyZZsyZM8yZAMxm/8xmzMxmmcxmZsxmM8xmAMwz/8wzzMwzmcwzZswzM8wzAMwA/8wAzMwAmcwAZswAM8wAAJn//5n/zJn/mZn/Zpn/M5n/AJnM/5nMzJnMmZnMZpnMM5nMAJmZ/5mZzJmZmZmZZpmZM5mZAJlm/5lmzJlmmZlmZplmM5lmAJkz/5kzzJkzmZkzZpkzM5kzAJkA/5kAzJkAmZkAZpkAM5kAAGb//2b/zGb/mWb/Zmb/M2b/AGbM/2bMzGbMmWbMZmbMM2bMAGaZ/2aZzGaZmWaZZmaZM2aZAGZm/2ZmzGZmmWZmZmZmM2ZmAGYz/2YzzGYzmWYzZmYzM2YzAGYA/2YAzGYAmWYAZmYAM2YAADP//zP/zDP/mTP/ZjP/MzP/ADPM/zPMzDPMmTPMZjPMMzPMADOZ/zOZzDOZmTOZZjOZMzOZADNm/zNmzDNmmTNmZjNmMzNmADMz/zMzzDMzmTMzZjMzMzMzADMA/zMAzDMAmTMAZjMAMzMAAAD//wD/zAD/mQD/ZgD/MwD/AADM/wDMzADMmQDMZgDMMwDMAACZ/wCZzACZmQCZZgCZMwCZAABm/wBmzABmmQBmZgBmMwBmAAAz/wAzzAAzmQAzZgAzMwAzAAAA/wAAzAAAmQAAZgAAMwAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAANgALAAAAAAaAAwAAAhxALEJHEiwoMGDBVcpVIiw4cBVAFRMk0hw4SqHAlepoLLqz7SEADg6VEiFI8WHEzlefGhRxaqSHT8SnAbT5cKSMDnWlJmRps6Of/5Y7PiSo8eCPokuTFhUI09sq5KuRNg0asKgU6litZLVIsaMXr9iCwgAOw==
\ No newline at end of file
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/test/kinematics/Makefile ./tools/test/kinematics/Makefile
--- ../Tekkotsu_2.4/tools/test/kinematics/Makefile	Wed Jun  1 01:48:09 2005
+++ ./tools/test/kinematics/Makefile	Tue Aug 16 16:13:26 2005
@@ -1,42 +1,46 @@
 
-#if you want to change the target model, it is recommended
-#to set the TEKKOTSU_TARGET_MODEL environment variable
+# This Makefile will handle most aspects of compiling and
+# linking a tool against the Tekkotsu framework.  You probably
+# won't need to make any modifications, but here's the major controls
 
-.PHONY: all
+# Executable name, defaults to:
+#   `basename \`pwd\``-$(TEKKOTSU_TARGET_MODEL)
+TEKKOTSU_TARGET_MODEL?=TGT_ERS7
+BIN:=$(shell pwd | sed 's@.*/@@')-$(shell echo $(patsubst TGT_%,%,$(TEKKOTSU_TARGET_MODEL)))
 
-# We use this TK_RT instead of TEKKOTSU_ROOT so things will
-# still work if TEKKOTSU_ROOT is a relative path from some
-# unknown project directory (and thus would be invalid from
-# this subdirectory of 'tools')
-TK_RT:=../../..
+# Build directory
+PROJECT_BUILDDIR:=build
 
-TEMPLATE_PROJECT:=$(TK_RT)/project
+# Source files, defaults to all files ending matching *$(SRCSUFFIX)
+SRCSUFFIX:=.cc
+PROJ_SRC:=$(shell find . -name "*$(SRCSUFFIX)")
+
+# We use a hard-coded TEKKOTSU_ROOT so this tool is always linked against the
+# the framework directory which contains it
+TEKKOTSU_ROOT=../../..
+
+.PHONY: all test
+
+TEMPLATE_PROJECT:=$(TEKKOTSU_ROOT)/project
 TEKKOTSU_ENVIRONMENT_CONFIGURATION?=$(TEMPLATE_PROJECT)/Environment.conf
-$(if $(shell if [ \! -r $(TEKKOTSU_ENVIRONMENT_CONFIGURATION) ] \; then echo failure \; fi),$(error An error has occured, `$(TEKKOTSU_ENVIRONMENT_CONFIGURATION)' could not be found.  You may need to edit TK_RT in the Makefile))
+$(if $(shell if [ \! -r $(TEKKOTSU_ENVIRONMENT_CONFIGURATION) ] \; then echo failure \; fi),$(error An error has occured, `$(TEKKOTSU_ENVIRONMENT_CONFIGURATION)' could not be found.  You may need to edit TEKKOTSU_ROOT in the Makefile))
 
 TEKKOTSU_TARGET_PLATFORM:=PLATFORM_LOCAL
-PROJECT_BUILDDIR:=build
 include $(TEKKOTSU_ENVIRONMENT_CONFIGURATION)
-FILTERSYSWARN:=$(patsubst $(TEKKOTSU_ROOT)/%,$(TK_RT)/%,$(FILTERSYSWARN))
-COLORFILT:=$(patsubst $(TEKKOTSU_ROOT)/%,$(TK_RT)/%,$(COLORFILT))
+FILTERSYSWARN:=$(patsubst $(TEKKOTSU_ROOT)/%,$(TEKKOTSU_ROOT)/%,$(FILTERSYSWARN))
+COLORFILT:=$(patsubst $(TEKKOTSU_ROOT)/%,$(TEKKOTSU_ROOT)/%,$(COLORFILT))
 $(shell mkdir -p $(PROJ_BD))
 
-BIN:=test_kinematics-$(shell echo $(patsubst TGT_%,%,$(TEKKOTSU_TARGET_MODEL)))
-
-SRCSUFFIX:=.cc
-
-PROJ_SRC:=$(shell find . -name "*$(SRCSUFFIX)")
-
 PROJ_OBJ:=$(patsubst ./%$(SRCSUFFIX),$(PROJ_BD)/%.o,$(PROJ_SRC))
 
 LIBS:= $(TK_BD)/libtekkotsu.a $(TK_BD)/../Motion/roboop/libroboop.a $(TK_BD)/../Shared/newmat/libnewmat.a
 
 DEPENDS:=$(PROJ_OBJ:.o=.d)
 
-CXXFLAGS=-g -Wall -O2 \
-         -I$(TK_RT) \
-         -D$(TEKKOTSU_TARGET_PLATFORM) -D$(TEKKOTSU_TARGET_MODEL) \
-	 `xml2-config --cflags`
+CXXFLAGS:=-g -Wall -O2 \
+         -I$(TEKKOTSU_ROOT) \
+         -I../../Shared/jpeg-6b $(shell xml2-config --cflags) \
+         -D$(TEKKOTSU_TARGET_PLATFORM) -D$(TEKKOTSU_TARGET_MODEL) 
 
 
 all: $(BIN)
@@ -73,3 +77,13 @@
 clean:
 	rm -rf $(BIN) $(PROJECT_BUILDDIR) *~
 
+test: $(BIN)
+	@for x in * ; do \
+		if [ -r "ideal-$$x" ] ; then \
+			if diff -u "ideal-$$x" "$$x" ; then \
+				echo "Test '$$x' passed"; \
+			else \
+				echo "Test output '$$x' does not match ideal"; \
+			fi; \
+		fi; \
+	done
\ No newline at end of file
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/test/network/Makefile ./tools/test/network/Makefile
--- ../Tekkotsu_2.4/tools/test/network/Makefile	Wed Jun  1 01:48:09 2005
+++ ./tools/test/network/Makefile	Tue Aug 16 16:13:28 2005
@@ -1,46 +1,49 @@
 
+# This Makefile will handle most aspects of compiling and
+# linking a tool against the Tekkotsu framework.  You probably
+# won't need to make any modifications, but here's the major controls
 
-#if you want to change the target model, it is recommended
-#to set the TEKKOTSU_TARGET_MODEL environment variable
+# Executable name, defaults to:
+#   `basename \`pwd\``-$(TEKKOTSU_TARGET_MODEL)
+TEKKOTSU_TARGET_MODEL?=TGT_ERS7
+BIN:=$(shell pwd | sed 's@.*/@@')-$(shell echo $(patsubst TGT_%,%,$(TEKKOTSU_TARGET_MODEL)))
 
-.PHONY: all tk
+# Build directory
+PROJECT_BUILDDIR:=build
 
-# We use this TK_RT instead of TEKKOTSU_ROOT so things will
-# still work if TEKKOTSU_ROOT is a relative path from some
-# unknown project directory (and thus would be invalid from
-# this subdirectory of 'tools')
-TK_RT:=../../..
+# Source files, defaults to all files ending matching *$(SRCSUFFIX)
+SRCSUFFIX:=.cc
+PROJ_SRC:=$(shell find . -name "*$(SRCSUFFIX)")
 
-TEMPLATE_PROJECT:=$(TK_RT)/project
+# We use a hard-coded TEKKOTSU_ROOT so this tool is always linked against the
+# the framework directory which contains it
+TEKKOTSU_ROOT=../../..
+
+.PHONY: all test
+
+TEMPLATE_PROJECT:=$(TEKKOTSU_ROOT)/project
 TEKKOTSU_ENVIRONMENT_CONFIGURATION?=$(TEMPLATE_PROJECT)/Environment.conf
-$(if $(shell if [ \! -r $(TEKKOTSU_ENVIRONMENT_CONFIGURATION) ] \; then echo failure \; fi),$(error An error has occured, `$(TEKKOTSU_ENVIRONMENT_CONFIGURATION)' could not be found.  You may need to edit TK_RT in the Makefile))
+$(if $(shell if [ \! -r $(TEKKOTSU_ENVIRONMENT_CONFIGURATION) ] \; then echo failure \; fi),$(error An error has occured, `$(TEKKOTSU_ENVIRONMENT_CONFIGURATION)' could not be found.  You may need to edit TEKKOTSU_ROOT in the Makefile))
 
 TEKKOTSU_TARGET_PLATFORM:=PLATFORM_LOCAL
-PROJECT_BUILDDIR:=build
 include $(TEKKOTSU_ENVIRONMENT_CONFIGURATION)
-FILTERSYSWARN:=$(patsubst $(TEKKOTSU_ROOT)/%,$(TK_RT)/%,$(FILTERSYSWARN))
-COLORFILT:=$(patsubst $(TEKKOTSU_ROOT)/%,$(TK_RT)/%,$(COLORFILT))
+FILTERSYSWARN:=$(patsubst $(TEKKOTSU_ROOT)/%,$(TEKKOTSU_ROOT)/%,$(FILTERSYSWARN))
+COLORFILT:=$(patsubst $(TEKKOTSU_ROOT)/%,$(TEKKOTSU_ROOT)/%,$(COLORFILT))
 $(shell mkdir -p $(PROJ_BD))
 
-BIN:=$(shell pwd | sed 's@.*/@@')-$(shell echo $(patsubst TGT_%,%,$(TEKKOTSU_TARGET_MODEL)))
-
-SRCSUFFIX:=.cc
-
-PROJ_SRC:=$(shell find . -name "*$(SRCSUFFIX)")
-
 PROJ_OBJ:=$(patsubst ./%$(SRCSUFFIX),$(PROJ_BD)/%.o,$(PROJ_SRC))
 
 LIBS:= $(TK_BD)/libtekkotsu.a $(TK_BD)/../Motion/roboop/libroboop.a $(TK_BD)/../Shared/newmat/libnewmat.a
 
 DEPENDS:=$(PROJ_OBJ:.o=.d)
 
-CXXFLAGS=-g -Wall -O2 \
-         -I$(TK_RT) \
-         -D$(TEKKOTSU_TARGET_PLATFORM) -D$(TEKKOTSU_TARGET_MODEL) \
-         `xml2-config --cflags`
+CXXFLAGS:=-g -Wall -O2 \
+         -I$(TEKKOTSU_ROOT) \
+         -I../../Shared/jpeg-6b $(shell xml2-config --cflags) \
+         -D$(TEKKOTSU_TARGET_PLATFORM) -D$(TEKKOTSU_TARGET_MODEL) 
 
 
-all: tk $(BIN)
+all: $(BIN)
 
 $(BIN): $(PROJ_OBJ) $(LIBS)
 	@echo "Linking $@..."
@@ -50,9 +53,6 @@
 -include $(DEPENDS)
 endif
 
-tk :
-	export TEKKOTSU_TARGET_PLATFORM=PLATFORM_LOCAL; $(MAKE) -C $(TK_RT) compile
-
 %.a :
 	@echo "ERROR: $@ was not found.  You may need to compile the Tekkotsu framework."
 	@echo "Press return to attempt to build it, ctl-C to cancel."
@@ -77,3 +77,13 @@
 clean:
 	rm -rf $(BIN) $(PROJECT_BUILDDIR) *~
 
+test: $(BIN)
+	@for x in * ; do \
+		if [ -r "ideal-$$x" ] ; then \
+			if diff -u "ideal-$$x" "$$x" ; then \
+				echo "Test '$$x' passed"; \
+			else \
+				echo "Test output '$$x' does not match ideal"; \
+			fi; \
+		fi; \
+	done
\ No newline at end of file
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/test/plist/Makefile ./tools/test/plist/Makefile
--- ../Tekkotsu_2.4/tools/test/plist/Makefile	Wed Jul 27 01:58:55 2005
+++ ./tools/test/plist/Makefile	Tue Aug 16 16:16:15 2005
@@ -15,11 +15,9 @@
 SRCSUFFIX:=.cc
 PROJ_SRC:=$(shell find . -name "*$(SRCSUFFIX)")
 
-# Other default values are drawn from the template project's
-# Environment.conf file.  This is found using $(TEKKOTSU_ROOT)
-# Remove the '?' if you want to override an environment variable
-# with a value of your own.
-TEKKOTSU_ROOT?=/usr/local/Tekkotsu
+# We use a hard-coded TEKKOTSU_ROOT so this tool is always linked against the
+# the framework directory which contains it
+TEKKOTSU_ROOT=../../..
 
 .PHONY: all test
 
@@ -80,7 +78,7 @@
 	rm -rf $(BIN) $(PROJECT_BUILDDIR) *~
 
 test: $(BIN)
-	@./plist-ERS7
+	./$(BIN)
 	@for x in * ; do \
 		if [ -r "ideal-$$x" ] ; then \
 			if diff -u "ideal-$$x" "$$x" ; then \
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/test/plist/ideal-virgin.plist ./tools/test/plist/ideal-virgin.plist
--- ../Tekkotsu_2.4/tools/test/plist/ideal-virgin.plist	Wed Jul 27 01:58:55 2005
+++ ./tools/test/plist/ideal-virgin.plist	Tue Aug 16 16:16:15 2005
@@ -1,11 +1,12 @@
 <?xml version="1.0"?>
 <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0"><dict>
+<!--======== numeric ========-->
 <!--numeric contains some numeric values
 	One is a float
 	The other is an int-->
 <key>numeric</key> <dict>
-    <key>fooF</key> <real>3.1415927410125732421875</real>
+    <key>fooF</key> <real>3.1415927410125732</real>
 
 <!--fooI: This is an integer value, the other is a float-->
     <key>fooI</key> <integer>42</integer>
diff -urdN --exclude=CVS -I\$[^$]*\$ ../Tekkotsu_2.4/tools/test/plist/ideal-vision.event ./tools/test/plist/ideal-vision.event
--- ../Tekkotsu_2.4/tools/test/plist/ideal-vision.event	Thu Jul 28 13:10:38 2005
+++ ./tools/test/plist/ideal-vision.event	Tue Aug 16 16:16:15 2005
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<event egid="visObjEGID" sid="0" etid="A" time="1" duration="0" magnitude="1">
+<event egid="visObjEGID" sid="0" etid="A" time="0" duration="0" magnitude="1">
   <param name="x1" value="0"/>
   <param name="y1" value="0"/>
   <param name="x2" value="0"/>
