between-6+dfsg1.orig/0000750000175000017500000000000011435543355013250 5ustar pabspabsbetween-6+dfsg1.orig/game7/0000750000175000017500000000000011435543354014247 5ustar pabspabsbetween-6+dfsg1.orig/game7/Makefile.GnuLinux0000640000175000017500000000150211103760155017446 0ustar pabspabs# # Modification History # # 2006-June-27 Jason Rohrer # Created. Condensed from X86 and PPC makefiles in Transcend project. # # 2007-April-23 Jason Rohrer # Removed unneeded libraries. # ## # The common GnuLinux portion of Makefiles. # Should not be made manually---used by configure to build Makefiles. ## PLATFORM_COMPILE_FLAGS = -DLINUX # various GL and X windows librariesneeded for linux # also need portaudio library (which in turn needs pthreads) PLATFORM_LINK_FLAGS = -L/usr/X11R6/lib -lGL -lGLU -lX11 -lSDL -lpthread # All platforms but OSX support g++ and need no linker hacks GXX = g++ LINK_FLAGS = ## # Platform-specific minorGems file path prefixes ## PLATFORM = Linux PLATFORM_PATH = linux TIME_PLATFORM = Unix TIME_PLATFORM_PATH = unix DIRECTORY_PLATFORM = Unix DIRECTORY_PLATFORM_PATH = unix between-6+dfsg1.orig/game7/gameSource/0000750000175000017500000000000011435543354016341 5ustar pabspabsbetween-6+dfsg1.orig/game7/gameSource/game.cpp0000640000175000017500000030473411377036601017767 0ustar pabspabs/* * Modification History * * 2008-September-11 Jason Rohrer * Created. Copied from Cultivation. */ #include #include #include #include #include // let SDL override our main function with SDLMain #include // must do this before SDL include to prevent WinMain linker errors on win32 int mainFunction( int inArgCount, char **inArgs ); int main( int inArgCount, char **inArgs ) { return mainFunction( inArgCount, inArgs ); } #include #include "minorGems/graphics/openGL/ScreenGL.h" #include "minorGems/graphics/openGL/SceneHandlerGL.h" #include "minorGems/graphics/Color.h" #include "minorGems/graphics/openGL/gui/GUIPanelGL.h" #include "minorGems/graphics/openGL/gui/GUITranslatorGL.h" #include "minorGems/graphics/openGL/gui/TextGL.h" #include "minorGems/graphics/openGL/gui/LabelGL.h" #include "minorGems/graphics/openGL/gui/TextFieldGL.h" #include "minorGems/system/Time.h" #include "minorGems/system/Thread.h" #include "minorGems/io/file/File.h" #include "minorGems/util/SettingsManager.h" #include "minorGems/util/TranslationManager.h" #include "minorGems/util/stringUtils.h" #include "minorGems/util/SimpleVector.h" #include "minorGems/util/random/StdRandomSource.h" StdRandomSource randSource; #include "common.h" #include "Sprite.h" #include "World.h" #include "Block.h" #include "BlockGrid.h" #include "TargetBlock.h" #include "BuilderTargetBlock.h" #include "HighlightLabelGL.h" #include "Client.h" #include "GridTransition.h" #include "NightBackground.h" #include "Player.h" #include "Star.h" #include "Cloud.h" #include "musicPlayer.h" // some settings // size of game image int gameWidth = 320; int gameHeight = 240; // size of screen for fullscreen mode int screenWidth = 640; int screenHeight = 480; int transitionSteps = 63; int animationFrameSteps = 2; int minSleepAnimationFrameSteps = 5; int numSleepFrames = 8; int rubbingEyesFrameSteps = 10; double baseScale = 1.0 / 16.0; double playerBaseHeight = 1; double playerSpeed = 0.0625; double leftWorldBoundary = -34; double rightWorldBoundary = 33; int numStars = 20; int numClouds = 30; int towerX = 7; class GameSceneHandler : public SceneHandlerGL, public MouseHandlerGL, public KeyboardHandlerGL, public RedrawListenerGL { public: /** * Constructs a sceen handler. * * @param inScreen the screen to interact with. * Must be destroyed by caller after this class is destroyed. */ GameSceneHandler( ScreenGL *inScreen ); virtual ~GameSceneHandler(); /** * Executes necessary init code that reads from files. * * Must be called before using a newly-constructed GameSceneHandler. * * This call assumes that the needed files are in the current working * directory. */ void initFromFiles(); ScreenGL *mScreen; // implements the SceneHandlerGL interface virtual void drawScene(); // implements the MouseHandlerGL interface virtual void mouseMoved( int inX, int inY ); virtual void mouseDragged( int inX, int inY ); virtual void mousePressed( int inX, int inY ); virtual void mouseReleased( int inX, int inY ); // implements the KeyboardHandlerGL interface virtual char isFocused() { // always focused return true; } virtual void keyPressed( unsigned char inKey, int inX, int inY ); virtual void specialKeyPressed( int inKey, int inX, int inY ); virtual void keyReleased( unsigned char inKey, int inX, int inY ); virtual void specialKeyReleased( int inKey, int inX, int inY ); // implements the RedrawListener interface virtual void fireRedraw(); protected: // sets the string on a label and re-centers it void setLabelString( LabelGL *inLabel, const char *inTranslationString, double inScaleFactor = 1.0 ); // creates a centerd label at a particular height HighlightLabelGL *createLabel( double inGuiY, const char *inTranslationString, TextGL *inText = NULL ); // the time that the last frame was drawn unsigned long mLastFrameSeconds; unsigned long mLastFrameMilliseconds; // our current frame rate unsigned long mFrameMillisecondDelta; int mStartTimeSeconds; char mPaused; double mMaxFrameRate; char mPrintFrameRate; unsigned long mNumFrames; unsigned long mFrameBatchSize; unsigned long mFrameBatchStartTimeSeconds; unsigned long mFrameBatchStartTimeMilliseconds; Color mBackgroundColor; Client *mClient; SimpleVector mOldClients; // for status display during game GUIPanelGL *mStatusPanel; GUITranslatorGL *mStatusPanelGuiTranslator; HighlightLabelGL *mStatusLabel; // for game selection display char mGUIVisible; GUIPanelGL *mMainPanel; GUITranslatorGL *mMainPanelGuiTranslator; TextGL *mTextGL; TextGL *mTextGLFixedWidth; GUIPanelGL *mCurrentPanel; GUIPanelGL *mTitlePanel; HighlightLabelGL *mTitleLabel; GUIPanelGL *mInitialRequestPanel; HighlightLabelGL *mInitialRequestLabel; double mInitialRequestPanelShownAtTime; GUIPanelGL *mSelectPanel; HighlightLabelGL *mCreateFriendLabel; HighlightLabelGL *mJoinFriendLabel; HighlightLabelGL *mJoinStrangerLabel; // track as array to make toggling easier HighlightLabelGL *mSelectLabels[3]; int mSelectHighlightIndex; GUIPanelGL *mWaitFriendPanel; HighlightLabelGL *mWaitFriendLabel; HighlightLabelGL *mGameIDLabel; GUIPanelGL *mWaitStrangerPanel; HighlightLabelGL *mWaitStrangerLabel; GUIPanelGL *mJoinFriendPanel; HighlightLabelGL *mEnterGameIDLabel; TextFieldGL *mEnterGameIDField; static const int mNumWorlds = 3; // extra world is used by transition grid World mWorlds[ mNumWorlds + 1]; BlockGrid mBlockGrids[ mNumWorlds + 1 ]; BlockGrid mTargetGrids[ mNumWorlds + 1 ]; // track all target blocks separate from the grid they are in SimpleVector mTargetBlocks[ mNumWorlds + 1 ]; SimpleVector mBuilderTargets[ mNumWorlds + 1 ]; // track all stars and clouds separate from the world they are in SimpleVector mStars[ mNumWorlds + 1 ]; SimpleVector mClouds[ mNumWorlds + 1 ]; // track all tiles in one big blob SimpleVector mTiles; // track all alarms stands separate from their world SimpleVector mAlarmStands; int mCurrentWorld; // -1 if not waiting for transition between worlds int mNextWorld; int mWorldTransitionDirection; GridTransition *mTransitionGrid; World *mTransitionWorld; // adjust toward this gradually (based on completeness of tower // in each world) double mMusicTrackFadeLevelTarget[ mNumWorlds + 1 ]; Player *mPlayer; char mLeftKeyDown; char mRightKeyDown; double mPlayerXDelta; double mPlayerFadeDelta; double mPlayerFadeUpperLimit; double mPlayerFadeLowerLimit; double mPlayerYSineParam; double mPlayerYSineDelta; int mStepsSinceAnimationFrame; char mCountingServerSteps; int mLastServerLatencyNumSteps; int mStepsPerSleepFrame; char mGoingToSleep; char mWakingUp; char mRubbingEyes; int mRubbingDirection; // count steps to make it consistent every time // matching last server latency // resets back to 0 every time we start going to sleep int mGoingToSleepSteps; int mTargetGoingToSleepSteps; // where player was last in each world // not that last one (corresponding to transition world) is never used // but array size is same so that same loops can be used. double mLastPlayerX[ mNumWorlds + 1]; GameObject *mSelector; char mSelectorInBounds; Block *mHoldingBlock; Sprite mSelectorSprite; Sprite mBuilderSprite; Sprite mBuilderTargetSprite; Sprite mBuilderHintSprite; // one shared in all worlds GameObject *mBuilderHint; Sprite mTileSprite; Sprite mNightTileSprite; Sprite mNightTileVerticalSprite; Sprite mNightTileCornerSprite; Sprite mBedSprite; Sprite mNightWindowSprite; Sprite mStarSprite; Sprite mMorningTileSprite; Sprite mMorningTileVerticalSprite; Sprite mMorningTileCornerSprite; Sprite mAlarmStandSprite; Sprite mMorningWindowSprite; Sprite mBackHintSprite; Sprite mNextHintSprite; Sprite mInsertHintSprite; char mDrawUpHint; char mDrawDownHint; double mUpHintFade; double mDownHintFade; Sprite mUpHintSprite; Sprite mDownHintSprite; Sprite mCloudSprite; // inserts a block into the current grid at current selector position void insertBlock( Block *inBlock ); // bounds the selector's Y position based on current block column void boundSelectorY(); }; GameSceneHandler *sceneHandler; ScreenGL *screen; // how many pixels wide is each game pixel drawn as? int pixelZoomFactor; Color ourColors[3] = { Color( 1.0, 0, 0 ), Color( 0, 1.0, 0 ), Color( 0, 0, 1.0 ) }; char ourColorCodes[3] = { 'A', 'B', 'C' }; // GameObject because this can hold a BlendedBlock at index 3 during transition GameObject *ourAvailableBlocks[4]; int ourCurrentBlockIndex; // used on palate during transition Block *oldConstructedBlock = NULL; Block *newConstructedBlock = NULL; BlendedBlock *transitionConstructedBlock = NULL; // fade out hints after they've each been used enough //... what's enough? 10 times each int numTimesHintsUsedBeforeFade = 10; // hint types: // (don't track W and S keys, because those hints can't be turned off anyway) enum HintType { HINT_SPACE = 0, HINT_N, HINT_B, HINT_UP, HINT_DOWN, NUM_HINT_TYPES }; int hintUsedCount[ NUM_HINT_TYPES ]; char fadeOutHints = false; double hintFadeFactor = 1.0; // for music // 0 means no tracks playing // 1 means all tracks playing // 0.5 means first half of tracks playing, rest silent double musicTrackFadeLevel = 0; double loudnessAdjust = 1.0; double loudnessAdjustTarget = 1.0; Color theirColors[3] = { Color( 1.0, 1.0, 0 ), Color( 0, 1.0, 1.0 ), Color( 1.0, 0, 1.0 ) }; char theirColorCodes[3] = { 'D', 'E', 'F' }; // from common.h Color codeToColor( char inCode ) { switch( inCode ) { case 'A': return ourColors[0]; case 'B': return ourColors[1]; case 'C': return ourColors[2]; case 'D': return theirColors[0]; case 'E': return theirColors[1]; case 'F': return theirColors[2]; } // default return Color(); } void replaceChar( char *inString, char inTarget, char inReplacement ) { int length = strlen( inString ); for( int i=0; i screenHeight ) { // screen too short pixelZoomFactor = screenHeight / gameHeight; } // hack: new version of minorGems scales screen differently screen->setImageSize( pixelZoomFactor * gameWidth, //pixelZoomFactor * gameHeight ); pixelZoomFactor * gameWidth ); SDL_ShowCursor( SDL_DISABLE ); sceneHandler = new GameSceneHandler( screen ); for( int b=0; b<3; b++ ) { ourAvailableBlocks[b] = new Block( &( ourColors[b] ), ourColorCodes[b] ); } ourAvailableBlocks[3] = NULL; ourCurrentBlockIndex = 0; // also do file-dependent part of init for GameSceneHandler here // actually, constructor is file dependent anyway. sceneHandler->initFromFiles(); // register cleanup function, since screen->start() will never return atexit( cleanUpAtExit ); setMusicLoudness( 1 * loudnessAdjust ); startMusic( "music.tga" ); screen->switchTo2DMode(); screen->start(); return 0; } GameSceneHandler::GameSceneHandler( ScreenGL *inScreen ) : mScreen( inScreen ), mFrameMillisecondDelta( 0 ), mStartTimeSeconds( time( NULL ) ), mPaused( false ), mMaxFrameRate( 60 ), mPrintFrameRate( false ), mNumFrames( 0 ), mFrameBatchSize( 100 ), mFrameBatchStartTimeSeconds( time( NULL ) ), mFrameBatchStartTimeMilliseconds( 0 ), //mBackgroundColor( 0.75, 0.75, 0.75, 1 ), mBackgroundColor( 0, 0, 0, 1 ), mClient( new Client ), mSelectorSprite( "selector.tga", true, 4 ), mBuilderSprite( "blockBuilder.tga", true ), mBuilderTargetSprite( "blockBuilderTarget.tga", true ), mBuilderHintSprite( "builderHint.tga", true ), mTileSprite( "tile.tga", false, 1, 4 ), mNightTileSprite( "nightTile.tga" ), mNightTileVerticalSprite( "nightTileVertical.tga" ), mNightTileCornerSprite( "nightTileCorner.tga" ), mBedSprite( "bed.tga", true ), mNightWindowSprite( "nightWindow.tga", true ), mStarSprite( "star.tga", true ), mMorningTileSprite( "morningTile.tga" ), mMorningTileVerticalSprite( "morningTileVertical.tga" ), mMorningTileCornerSprite( "morningTileCorner.tga" ), mAlarmStandSprite( "alarmStand.tga", true, 1, 4 ), mMorningWindowSprite( "morningWindow.tga", true ), mBackHintSprite( "backHint.tga", true ), mNextHintSprite( "nextHint.tga", true ), mInsertHintSprite( "insertHint.tga", true ), mDrawUpHint( false ), mDrawDownHint( false ), mUpHintFade( 0 ), mDownHintFade( 0 ), mUpHintSprite( "upHint.tga", true ), mDownHintSprite( "downHint.tga", true ), mCloudSprite( "clouds.tga", false, 4 ) { glClearColor( mBackgroundColor.r, mBackgroundColor.g, mBackgroundColor.b, mBackgroundColor.a ); // set external pointer so it can be used in calls below sceneHandler = this; mScreen->addMouseHandler( this ); mScreen->addKeyboardHandler( this ); mScreen->addSceneHandler( this ); mScreen->addRedrawListener( this ); Time::getCurrentTime( &mLastFrameSeconds, &mLastFrameMilliseconds ); mPlayer = new Player(); mLeftKeyDown = false; mRightKeyDown = false; mPlayerXDelta = 0; mPlayerFadeDelta = 0; mPlayerFadeUpperLimit = 1.0; mPlayerFadeLowerLimit = 0; mPlayerYSineParam = 0; mPlayerYSineDelta = 0; mStepsSinceAnimationFrame = 0; mCountingServerSteps = false; mLastServerLatencyNumSteps = minSleepAnimationFrameSteps * numSleepFrames; // default until we can measure server response mStepsPerSleepFrame = minSleepAnimationFrameSteps; mGoingToSleep = false; mWakingUp = false; mRubbingEyes = false; mRubbingDirection = 1; mGoingToSleepSteps = 0; mTargetGoingToSleepSteps = mLastServerLatencyNumSteps; // we step it manually, since one object is shared by all worlds mPlayer->mEnableSteps = false; mPlayer->mScale = baseScale; mPlayer->mY = playerBaseHeight; mPlayer->mDepthLayer = 0; mSelector = new GameObject(); mSelector->mSprite = &mSelectorSprite; mSelector->mScale = baseScale; mSelector->mY = mPlayer->mY; mSelector->mDepthLayer = 1; mSelectorInBounds = true; mHoldingBlock = NULL; mCurrentWorld = 0; mNextWorld = -1; mWorldTransitionDirection = 0; mTransitionGrid = NULL; mTransitionWorld = &( mWorlds[ mNumWorlds ] ); // four base blocks copied into each world's target grid BuilderTargetBlock builderTargets[4] = { BuilderTargetBlock( &mBuilderTargetSprite ), BuilderTargetBlock( &mBuilderTargetSprite ), BuilderTargetBlock( &mBuilderTargetSprite ), BuilderTargetBlock( &mBuilderTargetSprite ) }; // int builderTargetsX[4] = { -1, 0, 0, -1 }; //int builderTargetsY[4] = { 0, 0, 1, 1 }; int builderTargetsX[4] = { -1, 0, 0, -1 }; int builderTargetsY[4] = { 1, 1, 2, 2 }; // shared by all worlds mBuilderHint = new GameObject(); mBuilderHint->mSprite = &mBuilderHintSprite; mBuilderHint->mScale = baseScale; mBuilderHint->mY = 0; mBuilderHint->mX = -0.5 - baseScale; mBuilderHint->mDepthLayer = 0; // start invisible mBuilderHint->mFadeFactor = 0; for( int w=0; wmSprite = &mBuilderSprite; builder->mScale = baseScale; builder->mDepthLayer = 3; builder->mX = -0.5; builder->mY = 1.5; mWorlds[w].add( builder ); // add builder targets for( int b=0; b<4; b++ ) { BuilderTargetBlock *blockCopy = builderTargets[b].copy(); mTargetGrids[w].add( blockCopy, builderTargetsX[b], builderTargetsY[b] ); mBuilderTargets[w].push_back( blockCopy ); } // add tiles for( int x=-20; x<=19; x++ ) { GameObject *tile = new GameObject(); tile->mSprite = &mTileSprite; tile->mScale = 1.0 / 16.0; tile->mDepthLayer = 2; tile->mX = x; mWorlds[w].add( tile ); mTiles.push_back( tile ); } // add transition tiles to night // add a few extra world tiles underneath (to be covered by // night tiles that fade in) for( int x=-21; x>-27; x-- ) { GameObject *tile = new GameObject(); tile->mSprite = &mTileSprite; tile->mScale = 1.0 / 16.0; tile->mDepthLayer = 2; tile->mX = x; mWorlds[w].add( tile ); mTiles.push_back( tile ); } // add fading-in night tiles on top, for a bit for( int x=-21; x>-27; x-- ) { GameObject *tile = new GameObject(); tile->mSprite = &mNightTileSprite; tile->mScale = 1.0 / 16.0; tile->mDepthLayer = 2; tile->mX = x; tile->mFadeFactor = 1 - (double)(x - (-26)) / 6; mWorlds[w].add( tile ); } // add solid night tiles all the rest of the way out for( int x=-27; x>leftWorldBoundary; x-- ) { GameObject *tile = new GameObject(); tile->mSprite = &mNightTileSprite; tile->mScale = 1.0 / 16.0; tile->mDepthLayer = 2; tile->mX = x; mWorlds[w].add( tile ); } // add vertical night tiles as left boundary for( int y=1; y<10; y++ ) { GameObject *tile = new GameObject(); tile->mSprite = &mNightTileVerticalSprite; tile->mScale = 1.0 / 16.0; tile->mDepthLayer = 2; tile->mX = leftWorldBoundary; tile->mY = y; mWorlds[w].add( tile ); } // neaten up corner GameObject *cornerNightTile = new GameObject(); cornerNightTile->mSprite = &mNightTileCornerSprite; cornerNightTile->mScale = 1.0 / 16.0; cornerNightTile->mDepthLayer = 2; cornerNightTile->mX = leftWorldBoundary; cornerNightTile->mY = 0; mWorlds[w].add( cornerNightTile ); NightBackground *night = new NightBackground( Color( 0, 0, 0 ), -1 ); night->mScale = baseScale; night->mDepthLayer = 3; night->mX = -21; night->mY = 4.5; mWorlds[w].add( night ); GameObject *bed = new GameObject(); bed->mSprite = &mBedSprite; bed->mScale = baseScale; bed->mDepthLayer = 3; bed->mX = leftWorldBoundary + 5; bed->mY = 1.5; mWorlds[w].add( bed ); GameObject *nightWindow = new GameObject(); nightWindow->mSprite = &mNightWindowSprite; nightWindow->mScale = baseScale; nightWindow->mDepthLayer = 3; nightWindow->mX = leftWorldBoundary + 2; nightWindow->mY = 2.5; mWorlds[w].add( nightWindow ); // add some stars for( int s=0; smSprite = &mStarSprite; star->mScale = baseScale; star->mDepthLayer = 3; star->mX = randSource.getRandomBoundedDouble( leftWorldBoundary + 0.5, -23.5 ); star->mY = randSource.getRandomBoundedDouble( 4, 9.5 ); double yFadeFactor = 1.0; if( star->mY < 6 ) { yFadeFactor = ( (star->mY - 4) / ( 6 - 4 ) ); } double xFadeFactor = 1.0; if( star->mX > -26.5 ) { xFadeFactor = ( (star->mX - (-23.5)) / ( (-26.5) - (-23.5) ) ); } star->mBaseFade = yFadeFactor * xFadeFactor; mWorlds[w].add( star ); mStars[w].push_back( star ); } // now add morning stuff on right end // add transition tiles to morning // add a few extra world tiles underneath (to be covered by // morning tiles that fade in) for( int x=20; x<26; x++ ) { GameObject *tile = new GameObject(); tile->mSprite = &mTileSprite; tile->mScale = 1.0 / 16.0; tile->mDepthLayer = 2; tile->mX = x; mWorlds[w].add( tile ); mTiles.push_back( tile ); } // add fading-in morning tiles on top, for a bit for( int x=20; x<26; x++ ) { GameObject *tile = new GameObject(); tile->mSprite = &mMorningTileSprite; tile->mScale = 1.0 / 16.0; tile->mDepthLayer = 2; tile->mX = x; tile->mFadeFactor = (double)(x - 19) / 6; mWorlds[w].add( tile ); } // add solid morning tiles all the rest of the way out for( int x=26; xmSprite = &mMorningTileSprite; tile->mScale = 1.0 / 16.0; tile->mDepthLayer = 2; tile->mX = x; mWorlds[w].add( tile ); } // add vertical morning tiles as right boundary for( int y=1; y<10; y++ ) { GameObject *tile = new GameObject(); tile->mSprite = &mMorningTileVerticalSprite; tile->mScale = 1.0 / 16.0; tile->mDepthLayer = 2; tile->mX = rightWorldBoundary; tile->mY = y; mWorlds[w].add( tile ); } // neaten up corner GameObject *cornerMorningTile = new GameObject(); cornerMorningTile->mSprite = &mMorningTileCornerSprite; cornerMorningTile->mScale = 1.0 / 16.0; cornerMorningTile->mDepthLayer = 2; cornerMorningTile->mX = rightWorldBoundary; cornerMorningTile->mY = 0; mWorlds[w].add( cornerMorningTile ); // reuse night background for morning too NightBackground *morning = new NightBackground( Color( 1, 1, 0 ), 1 ); morning->mScale = baseScale; morning->mDepthLayer = 3; morning->mX = 20; morning->mY = 4.5; mWorlds[w].add( morning ); GameObject *alarmStand = new GameObject(); alarmStand->mSprite = &mAlarmStandSprite; alarmStand->mScale = baseScale; alarmStand->mDepthLayer = 3; alarmStand->mX = rightWorldBoundary - 5; alarmStand->mY = 1.5; mWorlds[w].add( alarmStand ); mAlarmStands.push_back( alarmStand ); GameObject *morningWindow = new GameObject(); morningWindow->mSprite = &mMorningWindowSprite; morningWindow->mScale = baseScale; morningWindow->mDepthLayer = 3; morningWindow->mX = rightWorldBoundary - 2; morningWindow->mY = 2.5; mWorlds[w].add( morningWindow ); // finally, clouds behind everything for( int c=0; cmSprite = &mCloudSprite; cloud->mScale = baseScale * 4; // fraction of clouds are in front of blocks and semi-transparent if( c < numClouds / 2 ) { cloud->mDepthLayer = 6; cloud->mBaseFade = 0.5; } else { // rest are behind and fully opaque cloud->mDepthLayer = 9; cloud->mBaseFade = 1.0; } cloud->mSpriteFrame = randSource.getRandomBoundedInt( 0, mCloudSprite.getNumFrames() - 1 ); cloud->mX = randSource.getRandomBoundedDouble( -27, 26 ); cloud->mY = randSource.getRandomBoundedDouble( 7, 10 ); double yFadeFactor = 1.0; if( cloud->mY < 9 ) { yFadeFactor = ( (cloud->mY - 7) / ( 9 - 7 ) ); } cloud->mBaseFade *= yFadeFactor; mWorlds[w].add( cloud ); mClouds[w].push_back( cloud ); } mMusicTrackFadeLevelTarget[w] = 0; } Block::staticInit(); // set up status UI mStatusPanel = new GUIPanelGL( 0, 0.75, 2, 0.25, new Color( 0, 0, 0, // transparent background 0 ) ); mStatusPanelGuiTranslator = new GUITranslatorGL( mStatusPanel, mScreen ); // no keyboard handler... status panel not interactive mScreen->addSceneHandler( mStatusPanelGuiTranslator ); // set up main UI mMainPanel = new GUIPanelGL( 0, 0, 2, 2, new Color( 0, 0, 0, 1.0 ) ); mMainPanelGuiTranslator = new GUITranslatorGL( mMainPanel, mScreen ); mScreen->addSceneHandler( mMainPanelGuiTranslator ); mScreen->addKeyboardHandler( mMainPanelGuiTranslator ); mGUIVisible = true; // construct sub-panels, but only add the first one mTitlePanel = new GUIPanelGL( 0, 0, 2, 2, new Color( 0, 0, 0, 1.0 ) ); mInitialRequestPanel = new GUIPanelGL( 0, 0, 2, 2, new Color( 0, 0, 0, 1.0 ) ); mSelectPanel = new GUIPanelGL( 0, 0, 2, 2, new Color( 0, 0, 0, 1.0 ) ); mWaitFriendPanel = new GUIPanelGL( 0, 0, 2, 2, new Color( 0, 0, 0, 1.0 ) ); mWaitStrangerPanel = new GUIPanelGL( 0, 0, 2, 2, new Color( 0, 0, 0, 1.0 ) ); mJoinFriendPanel = new GUIPanelGL( 0, 0, 2, 2, new Color( 0, 0, 0, 1.0 ) ); mMainPanel->add( mTitlePanel ); mCurrentPanel = mTitlePanel; } GameSceneHandler::~GameSceneHandler() { mScreen->removeMouseHandler( this ); mScreen->removeSceneHandler( this ); mScreen->removeRedrawListener( this ); for( int w=0; wremove( mTitlePanel ); mMainPanel->remove( mInitialRequestPanel ); mMainPanel->remove( mSelectPanel ); mMainPanel->remove( mWaitStrangerPanel ); mMainPanel->remove( mWaitFriendPanel ); mMainPanel->remove( mJoinFriendPanel ); delete mTitlePanel; delete mInitialRequestPanel; delete mSelectPanel; delete mWaitStrangerPanel; delete mWaitFriendPanel; delete mJoinFriendPanel; // this will recursively delete all status GUI components delete mStatusPanelGuiTranslator; // this will recursively delete all of our selector GUI components delete mMainPanelGuiTranslator; delete mTextGL; delete mTextGLFixedWidth; delete mClient; for( int i=0; isetText( labelString ); TextGL *text = inLabel->getTextGL(); int screenImageHeight = mScreen->getImageHeight(); // 1:1 aspect ratio // we know font is 6 pixels wide/tall double height = inScaleFactor * pixelZoomFactor * 6 * 1.0 / screenImageHeight; double width = height * strlen( labelString ); double actualDrawWidth = height * text->measureTextWidth( labelString ); // round to an integer number of pixels actualDrawWidth = round( actualDrawWidth * screenImageHeight ) / screenImageHeight; double centerW = 0.5 * (double)( mScreen->getImageWidth() ) / screenImageHeight; double guiY = inLabel->getAnchorY(); double labelX = centerW - 0.5 * actualDrawWidth; // round to an integer number of pixels labelX = round( labelX * screenImageHeight ) / screenImageHeight; guiY = round( guiY * screenImageHeight ) / screenImageHeight; inLabel->setPosition( labelX, guiY, width, height ); } HighlightLabelGL *GameSceneHandler::createLabel( double inGuiY, const char *inTranslationString, TextGL *inText ) { if( inText == NULL ) { inText = mTextGL; } HighlightLabelGL *returnLabel = new HighlightLabelGL( 0, inGuiY, 0, 0, "", inText ); setLabelString( returnLabel, inTranslationString ); return returnLabel; } void GameSceneHandler::initFromFiles() { // translation language File languageNameFile( NULL, "language.txt" ); if( languageNameFile.exists() ) { char *languageNameText = languageNameFile.readFileContents(); SimpleVector *tokens = tokenizeString( languageNameText ); int numTokens = tokens->size(); // first token is name if( numTokens > 0 ) { char *languageName = *( tokens->getElement( 0 ) ); TranslationManager::setLanguage( languageName ); } else { // default // TranslationManager already defaults to English, but // it looks for the language files at runtime before we have set // the current working directory. // Thus, we specify the default again here so that it looks // for its language files again. TranslationManager::setLanguage( "English" ); } delete [] languageNameText; for( int t=0; tgetElement( t ) ); } delete tokens; } // load text font Image *fontImage = readTGA( "font.tga" ); if( fontImage == NULL ) { // default // blank font fontImage = new Image( 256, 256, 4, true ); } mTextGL = new TextGL( fontImage, // use alpha true, // variable character width false, // extra space around each character 0.16666666666, // space is 5 pixels wide (out of 6) 0.83333333333 ); mTextGLFixedWidth = new TextGL( fontImage, // use alpha true, // fixed character width true, // extra space around each character 0, // space is full char width 1.0 ); delete fontImage; // now build gui panels based on labels, which depend on textGL // off screen! //mStatusLabel = createLabel( 0.95, "BROKEN" ); mStatusLabel = createLabel( 0.8, "" ); mStatusPanel->add( mStatusLabel ); mTitleLabel = createLabel( 0.50, "title" ); // increase scale setLabelString( mTitleLabel, "title", 2.0 ); mTitlePanel->add( mTitleLabel ); mInitialRequestLabel = createLabel( 0.65, "initialRequest" ); mInitialRequestPanel->add( mInitialRequestLabel ); mSelectLabels[0] = mCreateFriendLabel = createLabel( 0.6, "createForFriend" ); mSelectLabels[1] = mJoinFriendLabel = createLabel( 0.5, "joinWithFriend" ); mSelectLabels[2] = mJoinStrangerLabel = createLabel( 0.4, "joinWithStranger" ); mSelectPanel->add( mCreateFriendLabel ); mSelectPanel->add( mJoinFriendLabel ); mSelectPanel->add( mJoinStrangerLabel ); mSelectLabels[0]->setHighlight( true ); mSelectHighlightIndex = 0; mWaitFriendLabel = createLabel( 0.55, "creatingGame" ); mGameIDLabel = createLabel( 0.45, placeholderGameIDString, mTextGLFixedWidth ); mWaitFriendPanel->add( mWaitFriendLabel ); mWaitFriendPanel->add( mGameIDLabel ); mWaitStrangerLabel = createLabel( 0.55, "waitingForStranger" ); mWaitStrangerPanel->add( mWaitStrangerLabel ); mEnterGameIDLabel = createLabel( 0.55, "enterCode" ); mJoinFriendPanel->add( mEnterGameIDLabel ); // 1:1 aspect ratio // we know font is 6 pixels wide/tall double height = pixelZoomFactor * 6 * 1.0 / mScreen->getImageHeight(); double width = height * gameIDLength; double centerW = 0.5 * (double)( mScreen->getImageWidth() ) / mScreen->getImageHeight(); mEnterGameIDField = new TextFieldGL( centerW - 0.5 * width, 0.45, width, height, // 1 pixel wide border pixelZoomFactor * 1.0 / mScreen->getImageHeight(), "", mTextGLFixedWidth, new Color( 0.75, 0.75, 0.75 ), new Color( 0.75, 0.75, 0.75 ), new Color( 0.15, 0.15, 0.15 ), new Color( 0.75, 0.75, 0.75 ), gameIDLength, true ); mJoinFriendPanel->add( mEnterGameIDField ); // load target image and split it into blocks Image *targetImage = readTGA( "target.tga" ); int w = targetImage->getWidth(); int h = targetImage->getHeight(); int blocksWide = w / 16; // one extra row of pixels at bottom defines color map int blocksHigh = h / 16; // build color map, mapping A to B, and also to codes Color mapA[6]; Color mapB[6] = { ourColors[0], ourColors[1], ourColors[2], theirColors[0], theirColors[1], theirColors[2] }; char mapCodes[6] = { ourColorCodes[0], ourColorCodes[1], ourColorCodes[2], theirColorCodes[0], theirColorCodes[1], theirColorCodes[2] }; // read A key from bottom line of image int lineY = h - 1; int startIndex = lineY * w; for( int i=0; i<6; i++ ) { int index = startIndex + i; for( int c=0; c<3; c++ ) { ( mapA[i] )[c] = ( targetImage->getChannel( c ) )[ index ]; } /* printf( "Color map a = " ); mapA[i].print(); printf( "\n" ); */ } // now read blocks // starting position in grid (where to place by=0, bx=0 int gridY = 9; // center at towerX int gridX = towerX - 1; // add in reverse order, bottom up for( int by=blocksHigh-1; by>=0; by-- ) { for( int bx=0; bxgetSubImage( bx * 16, by * 16, 16, 16 ); // transform the block's color // and map to codes char blockColorCodes[257]; for( int i=0; i<256; i++ ) { int mapIndex = 0; char foundMatch = false; Color c = blockImage->getColor( i ); while( mapIndex < 6 && !foundMatch ) { if( mapA[ mapIndex ].equals( &c ) ) { foundMatch = true; } else { mapIndex++; } } if( foundMatch ) { blockColorCodes[i] = mapCodes[ mapIndex ]; blockImage->setColor( i, mapB[ mapIndex ] ); } } blockColorCodes[256] = '\0'; char *colorSig = Block::runLengthEncode( blockColorCodes ); TargetBlock *block = new TargetBlock( blockImage, colorSig ); // dummy block for testing // Block *dummy = new Block( blockImage, colorSig ); delete blockImage; delete [] colorSig; // add to target in each world for( int w=0; wcopy(); mTargetGrids[w].add( blockCopy, gridX + bx, gridY - by ); /* if( w < mNumWorlds ) { Block *dummyCopy = dummy->copy(); mBlockGrids[w].add( dummyCopy, gridX + bx - 5, gridY - by ); } */ mTargetBlocks[w].push_back( blockCopy ); } delete block; //delete dummy; } } delete targetImage; } double rot = 0; double rotDelta = 0.01; void GameSceneHandler::drawScene() { /* glClearColor( mBackgroundColor->r, mBackgroundColor->g, mBackgroundColor->b, mBackgroundColor->a ); */ glDisable( GL_TEXTURE_2D ); glDisable( GL_CULL_FACE ); glDisable( GL_DEPTH_TEST ); // sky glColor4d( 0.75, 0.75, 0.75, 1.0 ); glBegin( GL_QUADS ); { glVertex2d( -1, 1 ); glVertex2d( 1, 1 ); glVertex2d( 1, -1 ); glVertex2d( -1, -1 ); } glEnd(); if( mTransitionGrid == NULL ) { // scoot over one pixel mWorlds[ mCurrentWorld ].draw( mPlayer->mX - baseScale ); } else { // scoot over one pixel mTransitionWorld->draw( mPlayer->mX - baseScale ); } /* // draw sprites Vector3D posA( 0, 0, 0 ); //mTestSprite.draw( rot, &pos, 0.5 * sin( rot / 10 ) + 0.5 ); //rot += rotDelta; //mTestSpriteA.draw( rot, &posA, 0.03 ); Vector3D posB( 0.5, 0, 0 ); mTestSpriteA.draw( rot, &posB, 0.03 ); mTestSpriteB.draw( rot, &posB, 0.03 ); */ // letterbox glColor4d( 0, 0, 0, 1.0 ); glBegin( GL_QUADS ); { glVertex2d( -1, 1 ); glVertex2d( 1, 1 ); glVertex2d( 1, 0.5 ); glVertex2d( -1, 0.5 ); glVertex2d( -1, -1 ); glVertex2d( 1, -1 ); glVertex2d( 1, -0.5 ); glVertex2d( -1, -0.5 ); } glEnd(); // draw block palate on top of letterbox double palateScale = baseScale / 10.0; // keep palate centered, even during transition double xOffset = 0; double xOffsetA = 1 / 10.0; double xOffsetB = 0; if( transitionConstructedBlock == NULL ) { if( ourAvailableBlocks[3] == NULL ) { xOffset = xOffsetA; } else { xOffset = xOffsetB; } } else { double blend = transitionConstructedBlock->getFractionDone(); if( newConstructedBlock == NULL && oldConstructedBlock == NULL ) { xOffset = xOffsetA; } else if( newConstructedBlock != NULL && oldConstructedBlock == NULL ) { xOffset = blend * xOffsetB + (1 - blend) * xOffsetA; } else if( newConstructedBlock == NULL && oldConstructedBlock != NULL ) { xOffset = blend * xOffsetA + (1 - blend) * xOffsetB; } else if( newConstructedBlock != NULL && oldConstructedBlock != NULL ) { xOffset = xOffsetB; } } // key hints Vector3D hintPos( -2.25 * 2 / 10.0 + xOffset, -0.675, 0 ); mBackHintSprite.draw( 0, 0, &hintPos, palateScale, hintFadeFactor, NULL ); double nextHintPosA = 1.25 * 2 / 10.0; double nextHintPosB = 2.25 * 2 / 10.0; if( transitionConstructedBlock == NULL ) { if( ourAvailableBlocks[3] == NULL ) { hintPos.mX = nextHintPosA; } else { hintPos.mX = nextHintPosB; } } else { double blend = transitionConstructedBlock->getFractionDone(); if( newConstructedBlock == NULL && oldConstructedBlock == NULL ) { hintPos.mX = nextHintPosA; } else if( newConstructedBlock != NULL && oldConstructedBlock == NULL ) { hintPos.mX = blend * nextHintPosB + (1 - blend) * nextHintPosA; } else if( newConstructedBlock == NULL && oldConstructedBlock != NULL ) { hintPos.mX = blend * nextHintPosA + (1 - blend) * nextHintPosB; } else if( newConstructedBlock != NULL && oldConstructedBlock != NULL ) { hintPos.mX = nextHintPosB; } } hintPos.mX += xOffset; mNextHintSprite.draw( 0, 0, &hintPos, palateScale, hintFadeFactor, NULL ); // insert always centered at 0 as palate centering changes below it hintPos.mX = 0; hintPos.mY = -0.55; mInsertHintSprite.draw( 0, 0, &hintPos, palateScale, hintFadeFactor, NULL ); double selectorOffset = 0; for( int b=0; b<4; b++ ) { GameObject *block = ourAvailableBlocks[b]; if( block != NULL ) { double xBlockOffset = ( b - 1.5 ) * 2 / 10.0 + xOffset; if( b == ourCurrentBlockIndex ) { selectorOffset = xBlockOffset; } Vector3D blockPos( xBlockOffset, -0.675, 0 ); block->draw( 0, &blockPos, palateScale, 1, NULL ); } } // draw selector around current block Vector3D selectorPos( selectorOffset, -0.675, 0 ); mSelectorSprite.draw( 0, 0, &selectorPos, palateScale, 1, NULL ); hintPos.mY = -0.575; hintPos.mX = -0.9; if( mDrawUpHint ) { mUpHintSprite.draw( 0, 0, &hintPos, palateScale, mUpHintFade * hintFadeFactor, NULL ); } hintPos.mY -= 0.1; if( mDrawDownHint ) { mDownHintSprite.draw( 0, 0, &hintPos, palateScale, mDownHintFade * hintFadeFactor, NULL ); } } void GameSceneHandler::mouseMoved( int inX, int inY ) { } void GameSceneHandler::mouseDragged( int inX, int inY ) { } void GameSceneHandler::mousePressed( int inX, int inY ) { } void GameSceneHandler::mouseReleased( int inX, int inY ) { } void GameSceneHandler::fireRedraw() { if( mPaused ) { // ignore redraw event // sleep to avoid wasting CPU cycles Thread::staticSleep( 1000 ); // also ignore time that passes while paused Time::getCurrentTime( &mLastFrameSeconds, &mLastFrameMilliseconds ); return; } // deal with frame timing issues unsigned long lastMillisecondDelta = mFrameMillisecondDelta; // how many milliseconds have passed since the last frame mFrameMillisecondDelta = Time::getMillisecondsSince( mLastFrameSeconds, mLastFrameMilliseconds ); // lock down to mMaxFrameRate frames per second unsigned long minFrameTime = (unsigned long)( 1000 / mMaxFrameRate ); if( mFrameMillisecondDelta < minFrameTime ) { unsigned long timeToSleep = minFrameTime - mFrameMillisecondDelta; Thread::staticSleep( timeToSleep ); // get new frame second delta, including sleep time mFrameMillisecondDelta = Time::getMillisecondsSince( mLastFrameSeconds, mLastFrameMilliseconds ); } // avoid huge position "jumps" if we have a very large delay during a frame // (possibly caused by something going on in the background) // This will favor a slight visual slow down, but this is better than // a disorienting jump // skip this check if we are just starting up if( lastMillisecondDelta != 0 ) { if( mFrameMillisecondDelta > 6 * lastMillisecondDelta ) { // limit: this frame represents at most twice the jump of the last // frame // printf( "Limiting time jump (requested=%lu ms, last=%lu ms)\n", // mFrameMillisecondDelta, lastMillisecondDelta ); if( mFrameMillisecondDelta > 10000 ) { printf( "Time between frames more than 10 seconds:\n" ); // way too big... investigate printf( "Last time = %lu s, %lu ms\n", mLastFrameSeconds, mLastFrameMilliseconds ); Time::getCurrentTime( &mLastFrameSeconds, &mLastFrameMilliseconds ); printf( "current time = %lu s, %lu ms\n", mLastFrameSeconds, mLastFrameMilliseconds ); } mFrameMillisecondDelta = 2 * lastMillisecondDelta; } } // record the time that this frame was drawn Time::getCurrentTime( &mLastFrameSeconds, &mLastFrameMilliseconds ); // for use with non-constant time-per-frame // this game is constant time-per-frame // double frameSecondsDelta = (double)mFrameMillisecondDelta / 1000.0; mNumFrames ++; if( mPrintFrameRate ) { if( mNumFrames % mFrameBatchSize == 0 ) { // finished a batch unsigned long timeDelta = Time::getMillisecondsSince( mFrameBatchStartTimeSeconds, mFrameBatchStartTimeMilliseconds ); double frameRate = 1000 * (double)mFrameBatchSize / (double)timeDelta; printf( "Frame rate = %f frames/second\n", frameRate ); mFrameBatchStartTimeSeconds = mLastFrameSeconds; mFrameBatchStartTimeMilliseconds = mLastFrameMilliseconds; } } // process old clients to clear pending ops and destroy them for( int i=0; istep() == false ) { // done delete c; mOldClients.deleteElement( i ); i--; } } // deal with current network client operations // and pending startup menu operations if( ! mClient->isError() ) { char clientWorkLeft = mClient->step(); if( !clientWorkLeft ) { // end measurement, if we were conducting one if( mCountingServerSteps ) { //printf( "Server took %d steps to respond\n", // mLastServerLatencyNumSteps ); } mCountingServerSteps = false; } if( mNextWorld != -1 && ! clientWorkLeft && ! mGoingToSleep && mGoingToSleepSteps >= mTargetGoingToSleepSteps && mPlayerFadeDelta == 0 ) { // done fetching any state from server // and done with server latency cloaking animation // start transition if( mTransitionGrid == NULL ) { mTransitionGrid = new GridTransition( &( mBlockGrids[ mCurrentWorld ] ), &( mBlockGrids[ mNextWorld ] ), mTransitionWorld, transitionSteps ); // transition stars int i; for( i=0; ishiftBetween( *( mStars[ mCurrentWorld ].getElement( i ) ), *( mStars[ mNextWorld ].getElement( i ) ), transitionSteps ); } // transition clouds for( i=0; ishiftBetween( *( mClouds[ mCurrentWorld ].getElement( i ) ), *( mClouds[ mNextWorld ].getElement( i ) ), transitionSteps ); } // transition tiles int numTiles = mTiles.size(); for( i=0; ishiftBetweenPages( mCurrentWorld, mNextWorld, transitionSteps ); } // transition alarm stands int numAlarmStands = mAlarmStands.size(); for( i=0; ishiftBetweenPages( mCurrentWorld, mNextWorld, transitionSteps ); } // transition constructed block on palate if( oldConstructedBlock != NULL || newConstructedBlock != NULL ) { transitionConstructedBlock = new BlendedBlock( oldConstructedBlock, newConstructedBlock, transitionSteps ); ourAvailableBlocks[3] = transitionConstructedBlock; } // auto switch selector position at *start* of transition // if it is moving left (to get out of way of hint that // is sliding in if( newConstructedBlock == NULL && ourCurrentBlockIndex == 3 ) { ourCurrentBlockIndex = 2; } // set up a transition to position in next world /* mPlayerXDelta = ( mLastPlayerX[ mNextWorld ] - mPlayer->mX ) / transitionSteps; */ mPlayer->shiftPosition( mLastPlayerX[ mNextWorld ], transitionSteps ); mStepsSinceAnimationFrame = 0; if( mWorldTransitionDirection == -1 ) { // fade out and y arc mPlayerFadeDelta = -1.0 / transitionSteps; mPlayerFadeLowerLimit = 0; mPlayerYSineParam = 0; mPlayerYSineDelta = M_PI / transitionSteps; } else if( mWorldTransitionDirection == 1 ) { mRubbingEyes = false; // snap to lying down frame (while faded out) mPlayer->setPage( 2 ); mPlayer->mSpriteFrame = 7; // fade in during y arc mPlayerFadeDelta = 1.0 / transitionSteps; mPlayerFadeUpperLimit = 1; mPlayerYSineParam = 0; mPlayerYSineDelta = M_PI / transitionSteps; } } } } else { //printf( "%s\n", mClient->getErrorString() ); } // give panel enough time to be read if( mCurrentPanel == mInitialRequestPanel && Time::getCurrentTime() - mInitialRequestPanelShownAtTime > 1 ) { // error? if( mClient->isError() ) { char *errorMessage = mClient->getErrorString(); if( errorMessage != NULL ) { setLabelString( mInitialRequestLabel, errorMessage ); } } else if( mClient->isClientReady() ) { // move on to selection panel mMainPanel->remove( mInitialRequestPanel ); mMainPanel->add( mSelectPanel ); mCurrentPanel = mSelectPanel; } } else if( mCurrentPanel == mWaitFriendPanel ) { // error? if( mClient->isError() ) { char *errorMessage = mClient->getErrorString(); if( errorMessage != NULL ) { setLabelString( mWaitFriendLabel, errorMessage ); } } else if( strcmp( mGameIDLabel->getText(), placeholderGameIDString ) == 0 ) { char *clientGameID = mClient->getGameID(); if( clientGameID != NULL ) { //printf( "setting ID to %s\n", clientGameID ); mGameIDLabel->setText( clientGameID ); setLabelString( mWaitFriendLabel, "waitingForFriend" ); } } else { // game ready yet? if( mClient->isGameReady() ) { // start playing mMainPanel->remove( mCurrentPanel ); mCurrentPanel = NULL; mScreen->removeSceneHandler( mMainPanelGuiTranslator ); mScreen->removeKeyboardHandler( mMainPanelGuiTranslator ); mGUIVisible = false; } } } else if( mCurrentPanel == mJoinFriendPanel ) { // error? if( mClient->isError() ) { char *errorMessage = mClient->getErrorString(); if( errorMessage != NULL ) { setLabelString( mEnterGameIDLabel, errorMessage ); } // re-enable text field for additional attempts mEnterGameIDField->setFocus( true ); } else if( mClient->isGameReady() ) { // start playing mMainPanel->remove( mCurrentPanel ); mCurrentPanel = NULL; mScreen->removeSceneHandler( mMainPanelGuiTranslator ); mScreen->removeKeyboardHandler( mMainPanelGuiTranslator ); mGUIVisible = false; } } else if( mCurrentPanel == mWaitStrangerPanel ) { // error? if( mClient->isError() ) { char *errorMessage = mClient->getErrorString(); if( errorMessage != NULL ) { setLabelString( mWaitStrangerLabel, errorMessage ); } } else if( mClient->isGameReady() ) { // start playing mMainPanel->remove( mCurrentPanel ); mCurrentPanel = NULL; mScreen->removeSceneHandler( mMainPanelGuiTranslator ); mScreen->removeKeyboardHandler( mMainPanelGuiTranslator ); mGUIVisible = false; } } if( !showingQuitQuestion ) { // report dead partner? unsigned long seconds = mClient->getSecondsSincePartnerActed(); // ten minutes if( seconds > 600 ) { unsigned long minutes = seconds / 60; char *sourceString = (char *)TranslationManager::translate( "otherSilent" ); char *numberString = autoSprintf( "%lu", minutes ); char found; char *labelString = replaceOnce( sourceString, "#VAR", numberString, &found ); setLabelString( mStatusLabel, labelString ); delete [] numberString; delete [] labelString; } else { // blank status setLabelString( mStatusLabel, "" ); } } // update world object positions mPlayer->mX += mPlayerXDelta; // stop at boundary if( mPlayer->mX < leftWorldBoundary + 0.625 ) { mPlayer->mX = leftWorldBoundary + 0.625; mPlayer->mSpriteFrame = 0; mPlayerXDelta = 0; } if( mPlayer->mX > rightWorldBoundary - 0.5625 ) { mPlayer->mX = rightWorldBoundary - 0.5625; mPlayer->mSpriteFrame = 0; mPlayerXDelta = 0; } mPlayer->mFadeFactor += mPlayerFadeDelta; // cap fade and stop at limits if( mPlayer->mFadeFactor < mPlayerFadeLowerLimit ) { mPlayer->mFadeFactor = mPlayerFadeLowerLimit; mPlayerFadeDelta = 0; } if( mPlayer->mFadeFactor > mPlayerFadeUpperLimit ) { mPlayer->mFadeFactor = mPlayerFadeUpperLimit; mPlayerFadeDelta = 0; } // advance y arc if( mPlayerYSineParam != 0 ) { mPlayer->mY = playerBaseHeight - 0.5 * sin( mPlayerYSineParam ); } if( mPlayerYSineDelta != 0 ) { mPlayerYSineParam += mPlayerYSineDelta; if( mPlayerYSineParam > M_PI ) { mPlayerYSineParam = 0; mPlayerYSineDelta = 0; mPlayer->mY = playerBaseHeight; } } // don't run walking animation in transition // or while waking/sleeping if( !mGoingToSleep && !mWakingUp && mNextWorld == -1 ) { if( mPlayerXDelta != 0 ) { if( mStepsSinceAnimationFrame >= animationFrameSteps ) { mStepsSinceAnimationFrame = 0; // update animation switch( mPlayer->mSpriteFrame ) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: mPlayer->mSpriteFrame ++; break; case 12: mPlayer->mSpriteFrame = 1; break; } } else { mStepsSinceAnimationFrame ++; } } else { mStepsSinceAnimationFrame = 0; // switch to still frame switch( mPlayer->mSpriteFrame ) { case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: mPlayer->mSpriteFrame = 0; break; } } } if( mGoingToSleep ) { if( mStepsSinceAnimationFrame >= mStepsPerSleepFrame ) { mStepsSinceAnimationFrame = 0; if( mPlayer->mSpriteFrame == 7 ) { mGoingToSleep = false; } else { mPlayer->mSpriteFrame ++; } } else { mStepsSinceAnimationFrame ++; } } if( mWakingUp ) { if( mStepsSinceAnimationFrame >= mStepsPerSleepFrame ) { mStepsSinceAnimationFrame = 0; if( mPlayer->mSpriteFrame == 0 ) { mWakingUp = false; mPlayer->setPage( 0 ); } else { mPlayer->mSpriteFrame --; } } else { mStepsSinceAnimationFrame ++; } } if( mRubbingEyes ) { if( mStepsSinceAnimationFrame >= rubbingEyesFrameSteps ) { mStepsSinceAnimationFrame = 0; mPlayer->mSpriteFrame += mRubbingDirection; if( mPlayer->mSpriteFrame > 15 ) { mPlayer->mSpriteFrame = 14; mRubbingDirection = - mRubbingDirection; } if( mPlayer->mSpriteFrame < 13 ) { mPlayer->mSpriteFrame = 14; mRubbingDirection = - mRubbingDirection; } } else { mStepsSinceAnimationFrame ++; } } // respond to key held down that was ignored during transition if( !mGoingToSleep && !mWakingUp && mNextWorld == -1 ) { if( mLeftKeyDown && ! mRightKeyDown ) { mPlayer->setFlipHorizontal( false ); mPlayer->setHorizontalOffset( 0 ); mPlayerXDelta = - playerSpeed; } else if( mRightKeyDown && ! mLeftKeyDown ) { mPlayer->setFlipHorizontal( true ); mPlayer->setHorizontalOffset( -1 ); mPlayerXDelta = + playerSpeed; } } if( mHoldingBlock != NULL ) { mHoldingBlock->mX = mPlayer->mX; } double oldSelectorX = mSelector->mX; mSelector->mX = rint( mPlayer->mX ); if( oldSelectorX != mSelector->mX ) { mSelector->mFadeFactor = 0; } if( mNextWorld == -1 ) { // fade selector in if( mSelector->mFadeFactor < 1 && mPlayerXDelta == 0 ) { mSelector->mFadeFactor += 0.02; if( mSelector->mFadeFactor > 1 ) { mSelector->mFadeFactor = 1; } } } else { // fade selector out if( mSelector->mFadeFactor > 0 ) { mSelector->mFadeFactor -= 0.02; if( mSelector->mFadeFactor < 0 ) { mSelector->mFadeFactor = 0; } } } if( mSelector->mX < -20 || mSelector->mX > 19 ) { // off grid mSelectorInBounds = false; mSelector->mFadeFactor = 0; if( mSelector->mX < -20 ) { mSelector->mX = -20; } if( mSelector->mX > 19 ) { mSelector->mX = 19; } if( mHoldingBlock ) { // drop it mWorlds[mCurrentWorld].remove( mHoldingBlock ); insertBlock( mHoldingBlock ); mHoldingBlock = NULL; mPlayer->setPage( 0 ); } } else { mSelectorInBounds = true; } // auto-fade up/down hints if( mDrawUpHint && mUpHintFade < 1 ) { mUpHintFade += 0.02; if( mUpHintFade > 1 ) { mUpHintFade = 1; } } if( mDrawDownHint && mDownHintFade < 1 ) { mDownHintFade += 0.02; if( mDownHintFade > 1 ) { mDownHintFade = 1; } } if( ! fadeOutHints ) { char allUsedEnough = true; for( int h=0; h 0 ) { hintFadeFactor -= 0.001; if( hintFadeFactor < 0 ) { hintFadeFactor = 0; } } if( mHoldingBlock != NULL && mBlockGrids[mCurrentWorld].isColumnFull( (int)( mSelector->mX ) ) ) { // too full to add the block we're holding // hide selector mSelector->mFadeFactor = 0; } boundSelectorY(); for( int w=0; wstep(); } // step player object manually mPlayer->mainStep(); if( mTransitionGrid != NULL ) { if( mTransitionGrid->isDone() ) { delete mTransitionGrid; mTransitionGrid = NULL; // switch to next world mPlayer->mX = mLastPlayerX[ mNextWorld ]; mCurrentWorld = mNextWorld; mNextWorld = -1; mTileSprite.setPage( mCurrentWorld ); mAlarmStandSprite.setPage( mCurrentWorld ); // switch to newly constructed block if( oldConstructedBlock != NULL ) { delete oldConstructedBlock; } if( transitionConstructedBlock != NULL ) { delete transitionConstructedBlock; } ourAvailableBlocks[3] = newConstructedBlock; oldConstructedBlock = NULL; newConstructedBlock = NULL; transitionConstructedBlock = NULL; // auto-switch palate selector to new block if( ourAvailableBlocks[3] != NULL ) { ourCurrentBlockIndex = 3; } // already moved it left in case where new block is NULL // at start of transition mPlayerXDelta = 0; if( mWorldTransitionDirection == -1 ) { // switch to standing mPlayer->mSpriteFrame = 0; mPlayer->setPage( 0 ); // fade in int fadeSteps = mLastServerLatencyNumSteps; // watch for server latency that's too short if( fadeSteps < numSleepFrames * minSleepAnimationFrameSteps ) { fadeSteps = numSleepFrames * minSleepAnimationFrameSteps; } mPlayerFadeDelta = 1.0 / fadeSteps; mPlayerFadeUpperLimit = 1; } else if( mWorldTransitionDirection == 1 ) { mGoingToSleep = false; // fixed rate for standing back up mStepsPerSleepFrame = minSleepAnimationFrameSteps; mPlayer->mSpriteFrame = 7; mWakingUp = true; mPlayer->setPage( 2 ); } // loudness fades back up loudnessAdjustTarget = 1.0; } } // set target block states (only in current world) int numBlocks = mTargetBlocks[mCurrentWorld].size(); // count number of matches in each row int numMatched[9] = {0,0,0,0,0,0,0,0,0}; char anyMismatched = false; int i; for( i=0; imX ), (int)( b->mY ) ); if( realBlock == NULL ) { b->setState( 0 ); } else { if( b->equal( realBlock ) ) { b->setState( 2 ); // match numMatched[ (int)(b->mY) - 1 ] ++; } else { // mismatch b->setState( 1 ); anyMismatched = true; } } } int highestRowWithFullMatch = -1; for( int r=0; r<9; r++ ) { if( numMatched[r] == 3 ) { highestRowWithFullMatch = r; } } if( anyMismatched ) { mMusicTrackFadeLevelTarget[mCurrentWorld] = 0; } else { // fade level based on higest row with full match // (each row essentially turns on a new track) mMusicTrackFadeLevelTarget[mCurrentWorld] = ( highestRowWithFullMatch + 1 ) / 9.0; if( highestRowWithFullMatch != 8 ) { // not completely full // let fullness of row above last full row tweak volume of // track up a bit more // so track doesn't turn on suddenly when row is finally full // also, gives player *some* feedback during completion of // first row. mMusicTrackFadeLevelTarget[mCurrentWorld] += ( numMatched[ highestRowWithFullMatch + 1 ] / 3.0 ) / 9.0; } } double musicTrackFadeLevelTarget = mMusicTrackFadeLevelTarget[ mCurrentWorld ]; if( mTransitionGrid != NULL ) { // in transition to next world // volume is down, so we can jump instantly to new track fade level musicTrackFadeLevelTarget = mMusicTrackFadeLevelTarget[ mNextWorld ]; musicTrackFadeLevel = musicTrackFadeLevelTarget; } // move fade level toward target if( musicTrackFadeLevel != musicTrackFadeLevelTarget ) { int dir = -1; if( musicTrackFadeLevelTarget > musicTrackFadeLevel ) { dir = 1; } musicTrackFadeLevel += dir * 0.005; if( ( dir == -1 && musicTrackFadeLevel < musicTrackFadeLevelTarget ) || ( dir == 1 && musicTrackFadeLevel > musicTrackFadeLevelTarget ) ) { musicTrackFadeLevel = musicTrackFadeLevelTarget; } } // move loudness adjust toward target if( loudnessAdjust != loudnessAdjustTarget ) { int dir = -1; if( loudnessAdjustTarget > loudnessAdjust ) { dir = 1; } loudnessAdjust += dir * 0.05; if( ( dir == -1 && loudnessAdjust < loudnessAdjustTarget ) || ( dir == 1 && loudnessAdjust > loudnessAdjustTarget ) ) { loudnessAdjust = loudnessAdjustTarget; } } // overall loudness (not track selection) based on distance from tower double xDistance = fabs( mPlayer->mX - towerX ); // assume we are 1 unit in front of tower (so volume = 1 when // xDistance = 0 ) // multiplying by fraction makes it wider double widthFactor = 0.5; double distance = sqrt( 1 + widthFactor * xDistance * xDistance ); double loudness = 1 / ( distance * distance ); setMusicLoudness( loudness * loudnessAdjust ); // fade constructor hint in if constructor full of blocks Block *constructorBlocks[4]; constructorBlocks[0] = mBlockGrids[mCurrentWorld].getBlock( -1, 2 ); constructorBlocks[1] = mBlockGrids[mCurrentWorld].getBlock( 0, 2 ); constructorBlocks[2] = mBlockGrids[mCurrentWorld].getBlock( -1, 1 ); constructorBlocks[3] = mBlockGrids[mCurrentWorld].getBlock( 0, 1 ); char allNonNull = true; for( int b=0; b<4; b++ ) { if( constructorBlocks[b] == NULL ) { allNonNull = false; } } if( allNonNull && mNextWorld == -1 ) { mBuilderHint->mFadeFactor += 0.02; if( mBuilderHint->mFadeFactor > 1 ) { mBuilderHint->mFadeFactor = 1; } } else { mBuilderHint->mFadeFactor -= 0.02; if( mBuilderHint->mFadeFactor < 0 ) { mBuilderHint->mFadeFactor = 0; } } // shimmer state of constructor targets numBlocks = mBuilderTargets[mCurrentWorld].size(); for( i=0; imX ), (int)( b->mY ) ); if( realBlock == NULL ) { b->setState( 0 ); } else { // block present b->setState( 2 ); } } if( mCountingServerSteps ) { mLastServerLatencyNumSteps ++; } mGoingToSleepSteps ++; } void GameSceneHandler::keyPressed( unsigned char inKey, int inX, int inY ) { if( mNextWorld != -1 || mWakingUp || mGoingToSleep ) { return; } // check if world changed int initWorldChange = false; if( mGUIVisible ) { if( mMainPanel->contains( mTitlePanel ) ) { // q or escape if( inKey == 'q' || inKey == 'Q' || inKey == 27 ) { exit( 0 ); } // any other key advances from title mMainPanel->remove( mCurrentPanel ); mMainPanel->add( mInitialRequestPanel ); mCurrentPanel = mInitialRequestPanel; mInitialRequestPanelShownAtTime = Time::getCurrentTime(); } else if( mMainPanel->contains( mInitialRequestPanel ) ) { // q or escape if( inKey == 'q' || inKey == 'Q' || inKey == 27 ) { exit( 0 ); } } else if( mMainPanel->contains( mSelectPanel ) ) { // q or escape if( inKey == 'q' || inKey == 'Q' || inKey == 27 ) { exit( 0 ); } // any key press triggers selection GUIPanelGL *panelToShow = NULL; switch( mSelectHighlightIndex ) { case 0: panelToShow = mWaitFriendPanel; mEnterGameIDField->setFocus( false ); setLabelString( mWaitFriendLabel, "creatingGame" ); setLabelString( mGameIDLabel, placeholderGameIDString ); mClient->createGame(); break; case 1: panelToShow = mJoinFriendPanel; setLabelString( mEnterGameIDLabel, "enterCode" ); mEnterGameIDField->setFocus( true ); break; case 2: panelToShow = mWaitStrangerPanel; mEnterGameIDField->setFocus( false ); mClient->joinGame( NULL ); break; } if( panelToShow != NULL ) { mMainPanel->remove( mSelectPanel ); mMainPanel->add( panelToShow ); mCurrentPanel = panelToShow; } } else { if( mMainPanel->contains( mJoinFriendPanel ) ) { // look for enter if( inKey == 13 && mEnterGameIDField->isFocused() ) { char *enteredID = mEnterGameIDField->getText(); if( strlen( enteredID ) > 0 ) { // disable further input mEnterGameIDField->setFocus( false ); setLabelString( mEnterGameIDLabel, "joiningWithFriend" ); // try again, clearing any old errors mClient->clearError(); mClient->joinGame( enteredID ); } } } // q or escape pressed in any sub-panel if( inKey == 'q' || inKey == 'Q' || inKey == 27 ) { // back up // wait for this client to finish before destroying it mOldClients.push_back( mClient ); // fresh client mClient = new Client(); mMainPanel->remove( mCurrentPanel ); if( mClient->isClientReady() ) { mMainPanel->add( mSelectPanel ); mCurrentPanel = mSelectPanel; } else { // still waiting for ID? // clear any error message setLabelString( mInitialRequestLabel, "initialRequest" ); mMainPanel->add( mInitialRequestPanel ); mCurrentPanel = mInitialRequestPanel; mInitialRequestPanelShownAtTime = Time::getCurrentTime(); } } } return; } // q or escape if( inKey == 'q' || inKey == 'Q' || inKey == 27 ) { if( !showingQuitQuestion ) { oldStatusText = stringDuplicate( mStatusLabel->getText() ); showingQuitQuestion = true; setLabelString( mStatusLabel, "quitQuestion" ); } } // answer to quit question? else if( showingQuitQuestion && ( inKey == 'y' || inKey == 'Y' ) ) { delete [] oldStatusText; oldStatusText = NULL; exit( 0 ); } else if( showingQuitQuestion && ( inKey == 'n' || inKey == 'N' ) ) { setLabelString( mStatusLabel, oldStatusText ); delete [] oldStatusText; oldStatusText = NULL; showingQuitQuestion = false; } else if( inKey == ' ' ) { hintUsedCount[ HINT_SPACE ] ++; if( mSelectorInBounds ) { boundSelectorY(); int x = (int)( mSelector->mX ); int y = (int)( mSelector->mY ); Block *existingBlock = mBlockGrids[mCurrentWorld].getBlock( x, y ); if( mHoldingBlock != NULL || existingBlock == NULL ) { if( !mBlockGrids[mCurrentWorld].isColumnFull( x ) ) { //printf( "Adding block\n" ); Block *b; if( mHoldingBlock != NULL ) { b = mHoldingBlock; mWorlds[mCurrentWorld].remove( mHoldingBlock ); mHoldingBlock = NULL; } else { Block *palateBlock = (Block *)( ourAvailableBlocks[ourCurrentBlockIndex] ); b = palateBlock ->copy(); } insertBlock( b ); mPlayer->setPage( 0 ); } } else { //printf( "Removing block\n" ); mHoldingBlock = mBlockGrids[mCurrentWorld].removeBlock( x, y ); mHoldingBlock->mX = mPlayer->mX; mHoldingBlock->mY = mPlayer->mY + baseScale * 11; mHoldingBlock->mDepthLayer = 1; mWorlds[ mCurrentWorld ].add( mHoldingBlock ); mPlayer->setPage( 1 ); } } } else if( inKey == 'w' || inKey == 'W' ) { mPlayerXDelta = 0; if( mHoldingBlock != NULL ) { mWorlds[mCurrentWorld].remove( mHoldingBlock ); boundSelectorY(); insertBlock( mHoldingBlock ); mHoldingBlock = NULL; mPlayer->setPage( 0 ); } oldConstructedBlock = (Block*)( ourAvailableBlocks[3] ); // build new available block out of blocks in constructor Block *constructorBlocks[4]; constructorBlocks[0] = mBlockGrids[mCurrentWorld].getBlock( -1, 2 ); constructorBlocks[1] = mBlockGrids[mCurrentWorld].getBlock( 0, 2 ); constructorBlocks[2] = mBlockGrids[mCurrentWorld].getBlock( -1, 1 ); constructorBlocks[3] = mBlockGrids[mCurrentWorld].getBlock( 0, 1 ); char allNonNull = true; for( int b=0; b<4; b++ ) { if( constructorBlocks[b] == NULL ) { allNonNull = false; } } if( allNonNull ) { newConstructedBlock = new Block( constructorBlocks ); } // move on to next world mWorldTransitionDirection = +1; mNextWorld = mCurrentWorld + 1; if( mNextWorld >= mNumWorlds ) { mNextWorld = 0; } initWorldChange = true; // fade out while we wait for server // time the fade to the last server time mStepsSinceAnimationFrame = 0; if( mLastServerLatencyNumSteps > 0 ) { mStepsPerSleepFrame = mLastServerLatencyNumSteps / numSleepFrames; if( mStepsPerSleepFrame < minSleepAnimationFrameSteps ) { mStepsPerSleepFrame = minSleepAnimationFrameSteps; } } mPlayerFadeDelta = -1.0 / ( mStepsPerSleepFrame * numSleepFrames ); mPlayerFadeLowerLimit = 0.0; mRubbingEyes = true; mRubbingDirection = 1; mPlayer->mSpriteFrame = 13; // wake up to wherever you went to sleep last in the next world // ( leave mLastPlayerX alone for new world ) } else if( inKey == 's' || inKey == 'S' ) { mPlayerXDelta = 0; if( mHoldingBlock != NULL ) { mWorlds[mCurrentWorld].remove( mHoldingBlock ); boundSelectorY(); insertBlock( mHoldingBlock ); mHoldingBlock = NULL; mPlayer->setPage( 0 ); } oldConstructedBlock = (Block *)( ourAvailableBlocks[3] ); newConstructedBlock = NULL; mWorldTransitionDirection = -1; mNextWorld = mCurrentWorld - 1; if( mNextWorld < 0 ) { mNextWorld = mNumWorlds - 1; } initWorldChange = true; // run lie down animation while we wait for server mGoingToSleep = true; mStepsSinceAnimationFrame = 0; mPlayer->mSpriteFrame = 0; mPlayer->setPage( 2 ); // don't time animation to server response time // instead, run animation at fixed speed and let player lie there // to wait for server mStepsPerSleepFrame = minSleepAnimationFrameSteps; // make sure we wait enough steps total (lying there for a while // if necessary) mGoingToSleepSteps = 0; mTargetGoingToSleepSteps = mLastServerLatencyNumSteps; // when going to sleep, you go to default starting location // for the world mLastPlayerX[ mNextWorld ] = 0; } else if( inKey == 'n' || inKey == 'N' ) { hintUsedCount[ HINT_N ] ++; ourCurrentBlockIndex ++; if( ourCurrentBlockIndex > 3 || ourAvailableBlocks[ourCurrentBlockIndex] == NULL ) { ourCurrentBlockIndex = 0; } } else if( inKey == 'b' || inKey == 'B' ) { hintUsedCount[ HINT_B ] ++; ourCurrentBlockIndex --; if( ourCurrentBlockIndex < 0 ) { if( ourAvailableBlocks[3] != NULL ) { ourCurrentBlockIndex = 3; } else { ourCurrentBlockIndex = 2; } } } if( initWorldChange ) { // fade music loudness at start of world change loudnessAdjustTarget = 0; // save position in this world mLastPlayerX[ mCurrentWorld ] = mPlayer->mX; int sharedWorldIndex = mClient->getSharedWorldIndex( mNumWorlds ); // printf( "Shared world = %d\n", sharedWorldIndex ); if( mCurrentWorld == sharedWorldIndex ) { // leaving shared world // post move //printf( "Posting move\n" ); char requestSent = mClient->postMove( &( mBlockGrids[sharedWorldIndex] ) ); mBlockGrids[sharedWorldIndex].clearDirtyFlags(); if( requestSent ) { // measure latency mCountingServerSteps = true; mLastServerLatencyNumSteps = 0; } } else if( mNextWorld == sharedWorldIndex ) { // entering shared world // get changes //printf( "Fetching changes\n" ); mClient->getChanges( &( mBlockGrids[sharedWorldIndex] ) ); // measure latency mCountingServerSteps = true; mLastServerLatencyNumSteps = 0; } } } void GameSceneHandler::keyReleased( unsigned char inKey, int inX, int inY ) { } void GameSceneHandler::specialKeyPressed( int inKey, int inX, int inY ) { // keep key states for later, whether we act on them now or not switch( inKey ) { case MG_KEY_LEFT: mLeftKeyDown = true; break; case MG_KEY_RIGHT: mRightKeyDown = true; break; } if( mNextWorld != -1 || mGoingToSleep ) { return; } if( mWakingUp ) { // allow vertical motion of selector only switch( inKey ) { case MG_KEY_UP: hintUsedCount[ HINT_UP ] ++; mSelector->mY += 1; break; case MG_KEY_DOWN: hintUsedCount[ HINT_DOWN ] ++; mSelector->mY -= 1; break; } return; } switch( inKey ) { case MG_KEY_LEFT: mPlayerXDelta = - playerSpeed; mPlayer->setFlipHorizontal( false ); mPlayer->setHorizontalOffset( 0 ); mPlayer->mSpriteFrame = 0; break; case MG_KEY_RIGHT: mPlayerXDelta = + playerSpeed; mPlayer->setFlipHorizontal( true ); mPlayer->setHorizontalOffset( -1 ); mPlayer->mSpriteFrame = 0; break; case MG_KEY_UP: hintUsedCount[ HINT_UP ] ++; mSelector->mY += 1; if( mGUIVisible && mMainPanel->contains( mSelectPanel ) ) { mSelectLabels[ mSelectHighlightIndex ]->setHighlight( false ); mSelectHighlightIndex --; if( mSelectHighlightIndex < 0 ) { mSelectHighlightIndex = 2; } mSelectLabels[ mSelectHighlightIndex ]->setHighlight( true ); } break; case MG_KEY_DOWN: hintUsedCount[ HINT_DOWN ] ++; mSelector->mY -= 1; if( mGUIVisible && mMainPanel->contains( mSelectPanel ) ) { mSelectLabels[ mSelectHighlightIndex ]->setHighlight( false ); mSelectHighlightIndex ++; if( mSelectHighlightIndex > 2 ) { mSelectHighlightIndex = 0; } mSelectLabels[ mSelectHighlightIndex ]->setHighlight( true ); } break; } } void GameSceneHandler::specialKeyReleased( int inKey, int inX, int inY ) { // keep key states for later, whether we act on them now or not switch( inKey ) { case MG_KEY_LEFT: mLeftKeyDown = false; break; case MG_KEY_RIGHT: mRightKeyDown = false; break; } if( mNextWorld != -1 || mWakingUp || mGoingToSleep ) { return; } switch( inKey ) { case MG_KEY_LEFT: if( mPlayerXDelta == - playerSpeed ) { mPlayerXDelta = 0; } break; case MG_KEY_RIGHT: if( mPlayerXDelta == + playerSpeed ) { mPlayerXDelta = 0; } break; } } void GameSceneHandler::insertBlock( Block *inBlock ) { inBlock->mX = rint( mSelector->mX ); inBlock->mY = mSelector->mY; int x = (int)( inBlock->mX ); int y = (int)( inBlock->mY ); char result = mBlockGrids[mCurrentWorld].add( inBlock, x, y ); if( !result ) { delete inBlock; } else { inBlock->fadeIn(); } } void GameSceneHandler::boundSelectorY() { int aboveTopBlockY = 1; int blockX = (int)( mSelector->mX ); while( mBlockGrids[mCurrentWorld].getBlock( blockX, aboveTopBlockY ) != NULL ) { aboveTopBlockY ++; } char columnFull = mBlockGrids[mCurrentWorld].isColumnFull( blockX ); if( mSelector->mY > aboveTopBlockY ) { mSelector->mY = aboveTopBlockY; } if( columnFull ) { if( mSelector->mY > aboveTopBlockY - 1 ) { mSelector->mY = aboveTopBlockY - 1; } } if( mSelector->mY < 1 ) { mSelector->mY = 1; } int canMoveUp = 1; int canMoveDown = 1; if( mSelector->mY == aboveTopBlockY || ( columnFull && ( mSelector->mY == aboveTopBlockY - 1 ) ) ) { canMoveUp = 0; } if( mSelector->mY == 1 ) { canMoveDown = 0; } // turn them on once and forever after they are first usable if( canMoveUp ) { mDrawUpHint = true; } if( canMoveDown ) { mDrawDownHint = true; } // leave at 0, since we're drawing the other up/down hints now // convert to binary digits to index sprite frame // mSelector->mSpriteFrame = ( canMoveDown << 1 | canMoveUp ); } between-6+dfsg1.orig/game7/gameSource/font.png0000640000175000017500000000307711103241564020013 0ustar pabspabs‰PNG  IHDR``múàoPLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*úIDATxÚíšÑn¬0 Dãˆÿÿ幫v!±!¶í«ªº®!0ëø8RC‘gï©E–š’@h©™S™d™‰b¢˜j’@¢Øï§ŽìwS^ ˆ˜ÿ—b(ÅÚTÿL®Wz*¾/˜ç¿°H[‘¥}¶v÷ ³ß®üqŠÁŠ]¿A|ýäc<Å‹éÏ /qÌÃÛ^_©kÇCàå|“öÞÍL±.ÀÁуGŠ@3zug¸qèu=Í¥ƒ›óûSÙ×wh)ã—"õ{ôJÖ?7ÆÍ©r¼1ór*/Àö1Œì¯g³Ý”³.¬» >&€°NãzBûP÷dZ‹]`߈5} âÄ1HÇzŠGïc"Ï뺣৹ž-Ÿ„M¥ŒþU¸Çœên󰞆 y^l|‰©™ß…@¦¾À]_âFBƒ–>[‹Ù¨" ž<…‹"Œ¹<;yÔ6 Í÷çK’z ³ôJ%  Ñ£»÷‚Æ(6½;E1ÌÊ©1íqi¸bu¶å„â)fD™Ü×H£c\ÏÅ=Þ¶é¶Øf¹6¤žgÔyŜŎêÿY®EK ¤ž ¢¯ÝQ´à*›-psjãΚD#ô¥sáºL›é|½½A²þƒ‹Áɱ†ÏÎø£NyjÎþá çbú-ÄáyŒk‹A|ûH‡nêôö‚­Ò‰-G¦ý‘îäJµßŠKQ˜²—ärë#ÓO_OPÌíM^ŸqKs»£TÞ%™µíñ ¬”rúÖÜQ«(Fz>õÆ:O%ƒÁyŠ÷Ì'ñ¸ˆÈó<Ó(V¾ÙJLR€ç²Ö¸½Á¥/œ”9Š-¢OÄã|¬G«8óàüù0³âf+â6ïþµXôèžW#>JºG±¿çÑkÀ·i $“@“‰b¢˜j’@¢˜(&ŠÉTƒ$ÅD1QL5HÉ$(&ЉbªAH‰b21KS ’@HÅD1Õ ™’@¢˜(&Š©I $ÅHûw‘l@(gÚIEND®B`‚between-6+dfsg1.orig/game7/gameSource/Block.cpp0000640000175000017500000003375211377036601020107 0ustar pabspabs#include "Block.h" #include "common.h" #include "minorGems/util/random/StdRandomSource.h" #include "minorGems/util/SimpleVector.h" #include "minorGems/util/stringUtils.h" extern StdRandomSource randSource; Image *Block::sBaseImage = NULL; Image *Block::sNoiseImage = NULL; void Block::staticInit() { sBaseImage = readTGA( "blockBase.tga" ); sNoiseImage = readTGA( "blockNoise.tga" ); } void Block::staticFree() { delete sBaseImage; delete sNoiseImage; } Block::Block( Color *inColor, char inColorCode ) { double r = inColor->r; double g = inColor->g; double b = inColor->b; // color signatures are run-length encoded mColorSignature = autoSprintf( "256%c", inColorCode ); int w= sBaseImage->getWidth(); int h=w; mOverlayImage = new Image( w, h, 3, false ); int numPixels = w * h; for( int i=0; igetChannel( 0 )[i] = r; mOverlayImage->getChannel( 1 )[i] = g; mOverlayImage->getChannel( 2 )[i] = b; } initFromOverlay(); } Block::Block( Image *inOverlayImage, const char *inColorSignature ) { mOverlayImage = inOverlayImage->copy(); mColorSignature = stringDuplicate( inColorSignature ); initFromOverlay(); } char *Block::runLengthEncode( const char *inString ) { SimpleVector encodedSig; int stringLength = strlen( inString ); int i = 0; while( i < stringLength ) { char c = inString[i]; int charCount = 1; i++; while( i < stringLength && inString[i] == c ) { charCount ++; i++; } if( charCount > 1 ) { // add string encoding of run length to vector char *countAsString = autoSprintf( "%d", charCount ); int countStringLength = strlen( countAsString ); for( int j=0; j decodedSig; char *remainingString = (char *)inString; while( remainingString[0] != '\0' ) { int runLength = 0; char code = ' '; int numRead = sscanf( remainingString, "%d%c", &runLength, &code ); if( numRead != 2 ) { // a run of length 1? numRead = sscanf( remainingString, "%c", &code ); if( numRead == 1 ) { runLength = 1; } } for( int r=0; rgetWidth(); int h=w; mOverlayImage = new Image( w, h, 3, false ); int numPixels = w * h; int numCodes = strlen( decodedSig ); int numSteps = numPixels; if( numPixels != numCodes ) { printf( "Error: color signature not right length\n" ); // use shorter to avoid overrun if( numCodes < numPixels ) { numSteps = numCodes; } } for( int i=0; isetColor( i, codeToColor( decodedSig[ i ] ) ); } delete [] decodedSig; initFromOverlay(); } Block::Block( Block *inBlocks[4] ) { // arrange like // [0 1] // [2 3] int w= sBaseImage->getWidth(); int h=w; mOverlayImage = new Image( w, h, 3, false ); //int numPixels = w * h; // construct full source signatures char fullSourceSignatures[4][256]; int s; for( s=0; s<4; s++ ) { char *sig = inBlocks[s]->getColorSignature(); char *fullSig = runLengthDecode( sig ); unsigned int lengthToCopy = 256; if( strlen( fullSig ) < lengthToCopy ) { lengthToCopy = strlen( fullSig ); printf( "Error: full block signature length = %d, " "expecting 256\n", lengthToCopy ); } memcpy( fullSourceSignatures[s], fullSig, lengthToCopy ); delete [] fullSig; } // now build a full overlay signature for this block // along with the overlay image (indexing color codes just like // we index pixels) // leave room at end for \0 char fullOverlaySignature[257]; for( int y=0; ygetOverlayImage(); // nearest neighbor scaling (skip every other pixel) int sourceX = (x - xOffset) * 2; int sourceY = (y - yOffset) * 2; int sourceIndex = sourceY * w + sourceX; fullOverlaySignature[ overlayIndex ] = fullSourceSignatures[ sourceBlock ][ sourceIndex ]; for( int c=0; c<3; c++ ) { double *overlayChannel = mOverlayImage->getChannel( c ); double *sourceChannel = sourceImage->getChannel( c ); overlayChannel[ overlayIndex ] = sourceChannel[ sourceIndex ]; } } } fullOverlaySignature[256] = '\0'; /* // debug: // check it for( int i=0; i<256; i++ ) { char code = fullOverlaySignature[i]; Color c = codeToColor( code ); Color imageC = mOverlayImage->getColor( i ); if( !imageC.equals( &c ) ) { printf( "Constructed signature does not match image at index " "%d: " "code = %c\n", i, code ); c.print(); printf( "\n" ); imageC.print(); printf( "\n" ); } } */ mColorSignature = runLengthEncode( fullOverlaySignature ); initFromOverlay(); } // constructs a block using a sprite Block::Block( Sprite *inSprite, const char *inColorSignature ) { mShifting = false; mFadingIn = false; mScale = 1.0 / 16.0; mColorSignature = stringDuplicate( inColorSignature ); mOverlayImage = NULL; mDeleteSprite = false; mSprite = inSprite; } void Block::initFromOverlay(){ //printf( "New block: %s\n", mColorSignature ); mShifting = false; mFadingIn = false; mScale = 1.0 / 16.0; // pick a different frame to source each quadrant int baseSpriteFrame[4]; int q; for( q=0; q<4; q++ ) { baseSpriteFrame[q] = randSource.getRandomBoundedInt( 0, 3 ); } // DONE: // Probably should copy background texture and modulate it with // overlay directly // There's no way to modulate the color of a drawn polygon with // another drawn polygon while still paying attention to the alpha // mask of the underlying polygon // Can use multiplicative blending, but that ignores the underlying // alpha. Even if we copied the alpha of the background texture // and used it as the alpha for the overlay, multiplicative blending // would cause it to be ignored. // Every block has a texture anyway, so we're not wasting texture // memory by doing this. int w= sBaseImage->getWidth(); int h=w; int numPixels = w * h; // jump to a random line in noise image // leaving room for a full WxH image starting at that line int noiseImageHeight = sNoiseImage->getHeight(); int noiseSpriteLineA = randSource.getRandomBoundedInt( 0, noiseImageHeight - h - 1 ); int noiseSpriteLineB = randSource.getRandomBoundedInt( 0, noiseImageHeight - h - 1 ); // mix overlay image with base image and build alpha Image spriteImage( w, h, 5, false ); // find transparency color double *baseR = sBaseImage->getChannel( 0 ); double *baseG = sBaseImage->getChannel( 1 ); double *baseB = sBaseImage->getChannel( 2 ); // index of transparency int tI = sBaseImage->getWidth() * ( sBaseImage->getHeight() - 1 ); // color of transparency double tR = baseR[tI]; double tG = baseG[tI]; double tB = baseB[tI]; int baseOffsetInQuad[4]; for( q=0; q<4; q++ ) { baseOffsetInQuad[q] = baseSpriteFrame[q] * numPixels; } int noiseOffsetA = noiseSpriteLineA * w; int noiseOffsetB = noiseSpriteLineB * w; double *noiseR = sNoiseImage->getChannel( 0 ); double *noiseG = sNoiseImage->getChannel( 1 ); double *noiseB = sNoiseImage->getChannel( 2 ); double *overlayR = mOverlayImage->getChannel( 0 ); double *overlayG = mOverlayImage->getChannel( 1 ); double *overlayB = mOverlayImage->getChannel( 2 ); double *spriteR = spriteImage.getChannel( 0 ); double *spriteG = spriteImage.getChannel( 1 ); double *spriteB = spriteImage.getChannel( 2 ); double *spriteA = spriteImage.getChannel( 3 ); int halfW = w / 2; int halfH = h / 2; for( int i=0; igetColorSignature() ); return ( result == 0 ); } void Block::draw( double inRotation, Vector3D *inPosition, double inScale, double inFadeFactor, Color *inColor ) { mSprite->draw( 0, inRotation, inPosition, inScale, inFadeFactor, inColor ); } void Block::step() { if( mShifting ) { if( mY > mShiftTargetY ) { mY -= 0.04; if( mY < mShiftTargetY ) { mY = mShiftTargetY; mShifting = false; } } else if( mY < mShiftTargetY ) { mY += 0.04; if( mY > mShiftTargetY ) { mY = mShiftTargetY; mShifting = false; } } else { mShifting = false; } } if( mFadingIn ) { mFadeFactor += 0.04; if( mFadeFactor > 1 ) { mFadeFactor = 1; mFadingIn = false; } } } void Block::shiftTo( double inY ) { mShifting = true; mShiftTargetY = inY; } void Block::stopShifting() { if( mShifting ) { mShiftTargetY = mY; mShifting = false; } } void Block::fadeIn() { mFadingIn = true; mFadeFactor = 0; } between-6+dfsg1.orig/game7/gameSource/TargetBlock.h0000640000175000017500000000153211377036601020712 0ustar pabspabs#ifndef TARGET_BLOCK_INCLUDED #define TARGET_BLOCK_INCLUDED #include "Block.h" class TargetBlock : public Block { public: TargetBlock( Image *inOverlayImage, const char *inColorSignature, int inShimmerTime = -1 ); TargetBlock( Sprite *inSprite, const char *inColorSignature, int inShimmerTime = -1 ); // set state // 0 = unmatched // 1 = mismatched // 2 = perfect match void setState( int inState ); // subclass copy function TargetBlock *copy(); // override step function virtual void step(); protected: int mState; int mShimmerTime; void initShimmerState( int inShimmerTime ); }; #endif between-6+dfsg1.orig/game7/gameSource/player.png0000640000175000017500000000343711102230144020330 0ustar pabspabs‰PNG  IHDR@Œ$çQPLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*ÚIDATxÚíÛ‘£0E5”cê Q)Eµ`3xŒ­6­G³‡šš/•í«~$ÁOHÁõ5…€X ˆ÷¿W|/³Œamd«Æ—OЗ’òÓ“þר¥¾ŸŸ5_s,"!„<çR#ÉxíB˯QÍeÎY÷ë]g!Å) çl¥a:úç…,)­œÔ^a5G·Ö3¥¬½ ˆ!¤ ³”æ«1ƒ8ÏÙ°ãø€xÀ´=vÂvWˆ–v›Îv¼_ð€©ËMGÓ“s®‘¦.7ýíU*Õü&D–^ô-ƒCÙô²a\þЦ_;>»¨ûJ¼O£ñÙ‹>ôîÚña«Ö9g“\ÔhDdI1!2x€àxàZ<`ÝlµåÐÄ›ë®Ð¤0ЂJ¿@;Þ=Dã8>b%AD¶2qÑ[˹YqGf€€xðÈ ¬·Ÿ ã‹îÀ®¡8Ü­b¸¥§jØtJ£©ê¦¿»ª÷¤u÷Ìi>½t|Üþ×ݱU¯5_ƒ›šÁÀÒKoï+ˆe^—ÖB‘Ì€@àxàÿæçL¯[7Û1M×4Z¯nq~À(ô§Ã(žÅø¸/5õ˜¸.D}ªP Øuí…0P0þ‚n·ýdWüÙžp™ø{àÇZMae´Z»Š?ÿp\úÆø]'Ê´ÑIÐo%'?âïß›£'î´_>ר8?As•éµüWüÃA>¬>ïÒ/«¤ìÏÕÏ”ðÄ_Vo5þ–3À8?n›o{+Žñ$ [üò{s¨ÍŠÿW Œaü³ õc0cÿñ˜ñ«• QÃ7àE}ÿùsW$î» w‚ áÅ–‰%ó¿5#ö‚‘¿¾ÿ`%@Ù‡ˆ¢/~Fþ‹ímP+Ë¢é¦Bü,ü“>s/Ÿ‰¢/~~” òœ¶1ÄOÊïAè+÷옗ÚÅÏË´ÚÕÎÁU9ñ3òcí6BLq¹Wütü<›IÏbxùË#$ÆCÉúø{ºT¦0^þÕ»4 Çßc&.©‰ŸŽß3f­F}ñ[ñK:Š¿ü I* ¿T CøËM˜T Lþ6›Ó¯e¨þ•¹ÿH:œœË©@R!4ü·¦hO…`û[õ@ ºøÂwzõ²!þ÷â'ånå‰zº;ôIEND®B`‚between-6+dfsg1.orig/game7/gameSource/Client.h0000640000175000017500000001037211377036601017731 0ustar pabspabs#ifndef CLIENT_INCLUDED #define CLIENT_INCLUDED #include "WebRequest.h" #include "BlockGrid.h" // request types: enum RequestType { NONE, GET_SERVER_URL, GET_ID, CREATE, JOIN_FRIEND, IS_PARTNER_READY, JOIN_STRANGER, REPORT_ALIVE, POST_MOVE, GET_CHANGES }; class QueuedRequest { public: QueuedRequest( RequestType inType, const char *inMethod, const char *inURL, const char *inBody ) : mType( inType ), mMethod( stringDuplicate( inMethod ) ), mURL( stringDuplicate( inURL ) ), mBody( NULL ) { if( inBody != NULL ) { mBody = stringDuplicate( inBody ); } } ~QueuedRequest() { delete [] mMethod; delete [] mURL; if( mBody != NULL ) { delete [] mBody; } } RequestType mType; char *mMethod; char *mURL; char *mBody; }; // encapsulates all game network client operations class Client { public: // creates client and starts to request a player_id from the server, // if needed Client(); ~Client(); // perform another step of any pending network operations // returns true if work remains to be done // returns false if client is done with all pending work char step(); // must return true before starting any operations below char isClientReady(); // these calls start operations void createGame(); // NULL to join game with stranger void joinGame( char *inGameID ); // posts dirty columns to server // returns true if some were dirty and a post to the server resulted char postMove( BlockGrid *inGrid ); // gets changes and adds them to inGrid void getChanges( BlockGrid *inGrid ); // result not destroyed by caller // NULL if not set yet char *getGameID(); // useful for detecting a zombie or disconnected partner unsigned long getSecondsSincePartnerActed(); char isGameReady(); // gets a random, yet constant-per-game (and same as partner) // world index // game must be ready before this call works int getSharedWorldIndex( int mNumWorlds ); char isError(); void clearError(); // destroyed internally char *getErrorString(); // frees static data for this class // must be called at app exit static void staticFree(); protected: // URL where we fetch server URL from char *mServerFinderURL; // only fetch once per application instance static char *sServerURL; char *mPlayerID; char *mGameID; char *mGamePasscode; char *mPlayerNumber; // self-reversing transform int mBlockTransform[16]; // set from comma-delimited list void setBlockTransformFromString( char *inTransformString ); char *transformColumnString( char *inColumnString ); char mGameReady; unsigned long mTimeLastCheckedReady; unsigned long mTimeBetweenChecks; // we report our alive status when we're otherwise idle unsigned long mTimeLastReportedAlive; unsigned long mTimeBetweenReports; unsigned long mSecondsSincePartnerActed; char *mLastStateSeen; BlockGrid *mGridToUpdate; char mError; char *mErrorString; // inErrorMessage copied internally // must be destroyed by caller void setError( const char *inErrorMessage ); RequestType mCurrentType; WebRequest *mCurrentRequest; SimpleVector mQueuedRequests; }; #endif between-6+dfsg1.orig/game7/gameSource/WebRequest.h0000640000175000017500000000252511077456623020611 0ustar pabspabs#ifndef WEB_REQUEST_INCLUDED #define WEB_REQUEST_INCLUDED #include "minorGems/network/Socket.h" #include "minorGems/network/HostAddress.h" #include "minorGems/network/LookupThread.h" // a non-blocking web request class WebRequest { public: // inMethod = GET, POST, etc. // inURL the url to retrieve // inBody the body of the request, can be NULL // request body must be in application/x-www-form-urlencoded format WebRequest( char *inMethod, char *inURL, char *inBody ); // if request is not complete, destruction cancels it ~WebRequest(); // take anoter non-blocking step // return 1 if request complete // return -1 if request hit an error // return 0 if request still in-progress int step(); // gets the response body as a \0-terminated string char *getResult(); protected: char mError; char *mRequest; int mRequestPosition; SimpleVector mResponse; char mResultReady; char *mResult; HostAddress *mSuppliedAddress; HostAddress *mNumericalAddress; LookupThread *mLookupThread; Socket *mSock; }; #endif between-6+dfsg1.orig/game7/gameSource/star.png0000640000175000017500000000154011102233701020000 0ustar pabspabs‰PNG  IHDR&“ )PLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*IDAT×cdðd€&†ÿÛþC8Œè2pqìMm¨fÖIEND®B`‚between-6+dfsg1.orig/game7/gameSource/downHint.png0000640000175000017500000000163111103112361020621 0ustar pabspabs‰PNG  IHDR‘h6PLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*TIDAT(ÏcdÈe 010ÐX 2§A¸—º†· è„à¢X4Àd™ð¨ O3áw ¦Ã˜°DÖ``ˆX‰`À£Fä´DLÄ1¾Ä˜àijþÀIEND®B`‚between-6+dfsg1.orig/game7/gameSource/BlockGrid.cpp0000640000175000017500000001670311103155474020707 0ustar pabspabs#include "BlockGrid.h" #include "minorGems/util/stringUtils.h" void BlockGrid::initBlocks() { for( int r=0; r=0 && c < mBlockColumns && r>=0 && r < mBlockRows ) { // in bounds if( ! isColumnFull( inX ) ) { // there's room inBlock->mX = inX; inBlock->mY = inY; inBlock->mDepthLayer = mDepthLayer; mWorld->add( inBlock ); if( mBlocks[r][c] != NULL ) { // other blocks in way // cause all blocks at or above to rise for( int r2=mBlockRows-2; r2>=r; r2-- ) { if( mBlocks[r2][c] != NULL ) { Block *b = mBlocks[r2][c]; // put in new grid spot mBlocks[r2 + 1][c]= b; mBlocks[r2][c] = NULL; // rise to new world position b->shiftTo( (r2 + 1) + 1 ); } } } mBlocks[r][c] = inBlock; mDirtyFlags[c] = true; return true; } } // failed to add return false; } SimpleVector *BlockGrid::getAllBlocks() { SimpleVector *returnVector = new SimpleVector(); for( int r=0; rpush_back( mBlocks[r][c] ); } } } return returnVector; } Block *BlockGrid::getBlock( int inX, int inY ) { int c = worldToGridC( inX ); int r = worldToGridR( inY ); if( c>=0 && c < mBlockColumns && r>=0 && r < mBlockRows ) { // in bounds return mBlocks[r][c]; } return NULL; } Block *BlockGrid::removeBlock( int inX, int inY ) { int c = worldToGridC( inX ); int r = worldToGridR( inY ); if( c>=0 && c < mBlockColumns && r>=0 && r < mBlockRows ) { // in bounds Block *returnBlock = mBlocks[r][c]; mBlocks[r][c] = NULL; mWorld->remove( returnBlock ); // cancel any shift for this block returnBlock->stopShifting(); // cause all blocks above to fall for( int r2=r+1; r2shiftTo( (r2 - 1) + 1 ); } } mDirtyFlags[c] = true; return returnBlock; } return NULL; } char BlockGrid::isColumnFull( int inX ) { int c = worldToGridC( inX ); if( c>=0 && c < mBlockColumns ) { // in bounds // check top spot only if( mBlocks[ mBlockRows - 1 ][c] != NULL ) { return true; } else { return false; } } else { // out of bounds always full return true; } } SimpleVector *BlockGrid::getDirtyColumns() { SimpleVector *returnVector = new SimpleVector(); for( int c=0; cgetColorSignature() ); char *newColumnString = concatonate( columnString, blockString ); delete [] blockString; delete [] columnString; columnString = newColumnString; r++; } if( r == 0 ) { // empty column // add _ after column number delete [] columnString; columnString = autoSprintf( "%d_", c ); } returnVector->push_back( columnString ); } } return returnVector; } void BlockGrid::clearDirtyFlags() { for( int c=0; c *inColumns ) { int numToSet = inColumns->size(); for( int i=0; igetElement( i ) ), "_", &numParts ); // first part is column number if( numParts > 0 ) { int c; int numRead = sscanf( parts[0], "%d", &c ); if( numRead == 1 ) { // first clear the column int r=0; while( rremove( b ); delete b; r++; } // now see if the new column has any blocks for( int p=1; pmX = gridToWorldX( c ); b->mY = gridToWorldY( r ); b->mDepthLayer = mDepthLayer; mBlocks[r][c] = b; mWorld->add( b ); } } } } for( int p=0; p #include #include #include // smoothly fade in particular tracks based on track fade level // low value plays only first track... high value plays all tracks extern double musicTrackFadeLevel; int sampleRate = 22050; //int sampleRate = 11025; Image *musicImage = NULL; int w, h; // total number of samples played so far int streamSamples = 0; // offset into grid at start // for testing int gridStartOffset = 0; // overal loudness of music double musicLoudness = 1.0; // one grid step in seconds double gridStepDuration = 0.25; int gridStepDurationInSamples = (int)( gridStepDuration * sampleRate ); double entireGridDuraton; // c double keyFrequency = 261.63; int numTimbres = 9; Timbre *musicTimbres[ 9 ]; int numEnvelopes = 9; Envelope *musicEnvelopes[ 9 ]; class Note { public: // index into musicTimbres array int mTimbreNumber; // index into musicEnvelopes array int mEnvelopeNumber; int mScaleNoteNumber; // additional loudness adjustment // places note in stereo space double mLoudnessLeft; double mLoudnessRight; // start time, in seconds from start of note grid double mStartTime; // duration in seconds double mDuration; // used when note is currently playing to track progress in note // negative if we should wait before starting to play the note int mCurrentSampleNumber; // duration in samples int mNumSamples; }; // isomorphic to our music image, except only has an entry for each note // start (all others, including grid spots that contain note continuations, // are NULL) // indexed as noteGrid[y][x] Note ***noteGrid; SimpleVector currentlyPlayingNotes; // need to synch these with audio thread void setMusicLoudness( double inLoudness ) { SDL_LockAudio(); musicLoudness = inLoudness; SDL_UnlockAudio(); } void restartMusic() { SDL_LockAudio(); // return to beginning (and forget samples we've played so far) streamSamples = 0; // drop all currently-playing notes currentlyPlayingNotes.deleteAll(); SDL_UnlockAudio(); } // called by SDL to get more samples void audioCallback( void *inUserData, Uint8 *inStream, int inLengthToFill ) { // 2 bytes for each channel of stereo sample int numSamples = inLengthToFill / 4; Sint16 *samplesL = new Sint16[ numSamples ]; Sint16 *samplesR = new Sint16[ numSamples ]; // first, zero-out the buffer to prepare it for our sum of note samples // each sample is 2 bytes memset( samplesL, 0, 2 * numSamples ); memset( samplesR, 0, 2 * numSamples ); int i; // hop through all grid steps that *start* in this stream buffer // add notes that start during this stream buffer // how far into stream buffer before we hit our first grid step? int startOfFirstGridStep = streamSamples % gridStepDurationInSamples; if( startOfFirstGridStep != 0 ) { startOfFirstGridStep = gridStepDurationInSamples - startOfFirstGridStep; } // hop from start of grid step to start of next grid step // ignore samples in between, since notes don't start there, // and all we're doing right now is finding notes that start for( i=startOfFirstGridStep; imCurrentSampleNumber = -i; } } } streamSamples += numSamples; // loop over all current notes and add their samples to buffer for( int n=0; nmScaleNoteNumber; Timbre *timbre = musicTimbres[ note->mTimbreNumber ]; int tableLength = timbre->mWaveTableLengths[ waveTableNumber ]; Sint16 *waveTable = timbre->mWaveTable[ waveTableNumber ]; Envelope *env = musicEnvelopes[ note->mEnvelopeNumber ]; double *envLevels = env->getEnvelope( // index envelope by number of grid steps in note note->mNumSamples / gridStepDurationInSamples ); double noteLoudnessL = note->mLoudnessLeft; double noteLoudnessR = note->mLoudnessRight; // do this outside inner loop noteLoudnessL *= musicLoudness; noteLoudnessR *= musicLoudness; // factor in externally-set track fade level // level from 0..(numTimbres) double trackFadeInLevel = musicTrackFadeLevel * (numTimbres); // level for this track based on trackFadeInLevel double thisTrackLevel; if( trackFadeInLevel >= note->mTimbreNumber + 1 ) { // full volume thisTrackLevel = 1.0; } else if( trackFadeInLevel > note->mTimbreNumber ) { // linear fade in for this track thisTrackLevel = trackFadeInLevel - (int)trackFadeInLevel; } else { // track silent thisTrackLevel = 0; } noteLoudnessL *= thisTrackLevel; noteLoudnessR *= thisTrackLevel; int noteStartInBuffer = 0; int noteEndInBuffer = numSamples; if( note->mCurrentSampleNumber < 0 ) { // delay before note starts in this sample buffer noteStartInBuffer = - note->mCurrentSampleNumber; // we've taken account of the delay note->mCurrentSampleNumber = 0; } char endNote = false; int numSamplesLeftInNote = note->mNumSamples - note->mCurrentSampleNumber; if( noteStartInBuffer + numSamplesLeftInNote < noteEndInBuffer ) { // note ends before end of buffer noteEndInBuffer = noteStartInBuffer + numSamplesLeftInNote; endNote = true; } int waveTablePos = note->mCurrentSampleNumber % tableLength; int currentSampleNumber = note->mCurrentSampleNumber; for( i=noteStartInBuffer; i != noteEndInBuffer; i++ ) { double envelope = envLevels[ currentSampleNumber ]; double monoSample = envelope * waveTable[ waveTablePos ]; samplesL[i] += (Sint16)( noteLoudnessL * monoSample ); samplesR[i] += (Sint16)( noteLoudnessR * monoSample ); currentSampleNumber ++; waveTablePos ++; // avoid using mod operator (%) in inner loop // found with profiler if( waveTablePos == tableLength ) { // back to start of table waveTablePos = 0; } } note->mCurrentSampleNumber += ( noteEndInBuffer - noteStartInBuffer ); if( endNote ) { // note ended in this buffer currentlyPlayingNotes.deleteElement( n ); n--; } } // now copy samples into Uint8 buffer int streamPosition = 0; for( i=0; i != numSamples; i++ ) { Sint16 intSampleL = samplesL[i]; Sint16 intSampleR = samplesR[i]; inStream[ streamPosition ] = (Uint8)( intSampleL & 0xFF ); inStream[ streamPosition + 1 ] = (Uint8)( ( intSampleL >> 8 ) & 0xFF ); inStream[ streamPosition + 2 ] = (Uint8)( intSampleR & 0xFF ); inStream[ streamPosition + 3 ] = (Uint8)( ( intSampleR >> 8 ) & 0xFF ); streamPosition += 4; } delete [] samplesL; delete [] samplesR; } // limit on n, based on Nyquist, when summing sine components //int nLimit = (int)( sampleRate * M_PI ); // actually, this is way too many: it takes forever to compute // use a lower limit instead // This produces fine results (almost perfect square wave) int nLimit = 40; // square wave with period of 2pi double squareWave( double inT ) { double sum = 0; for( int n=1; ngetWidth(); h = musicImage->getHeight(); // notes are in red and green channel double *redChannel = musicImage->getChannel( 0 ); double *greenChannel = musicImage->getChannel( 1 ); entireGridDuraton = gridStepDuration * w; // jump ahead in stream, if needed streamSamples += gridStartOffset * gridStepDurationInSamples; // blank line of pixels between timbres int heightPerTimbre = (h+1) / numTimbres - 1; // find the maximum number of simultaneous notes in the song // take loudness into account double maxNoteLoudnessInAColumn = 0; int x, y; for( x=0; x 0 || greenChannel[ imageIndex ] > 0 ) ) { noteLoudnessInColumnL += greenChannel[ imageIndex ]; noteLoudnessInColumnR += redChannel[ imageIndex ]; } } // pick loudest channel for this column and compare it to // loudest column/channel seen so far if( maxNoteLoudnessInAColumn < noteLoudnessInColumnL ) { maxNoteLoudnessInAColumn = noteLoudnessInColumnL; } if( maxNoteLoudnessInAColumn < noteLoudnessInColumnR ) { maxNoteLoudnessInAColumn = noteLoudnessInColumnR; } } // divide loudness amoung timbres to avoid clipping double loudnessPerTimbre = 1.0 / maxNoteLoudnessInAColumn; // further adjust loudness per channel here as we construct // each timbre. // This is easier than tweaking loundness of a given part by hand // using a painting program musicTimbres[0] = new Timbre( sampleRate, 0.4 * loudnessPerTimbre, keyFrequency / 2, heightPerTimbre, sin ); musicTimbres[1] = new Timbre( sampleRate, 0.3 * loudnessPerTimbre, keyFrequency, heightPerTimbre, harmonicSine ); musicTimbres[2] = new Timbre( sampleRate, 0.2 * loudnessPerTimbre, keyFrequency * 2, heightPerTimbre, sin ); musicTimbres[3] = new Timbre( sampleRate, 0.6 * loudnessPerTimbre, keyFrequency, heightPerTimbre, sin ); musicTimbres[4] = new Timbre( sampleRate, loudnessPerTimbre, keyFrequency, heightPerTimbre, sin ); musicTimbres[5] = new Timbre( sampleRate, 0.7 * loudnessPerTimbre, keyFrequency / 4, heightPerTimbre, harmonicSaw ); musicTimbres[6] = new Timbre( sampleRate, 0.4 * loudnessPerTimbre, keyFrequency, heightPerTimbre, harmonicSaw ); musicTimbres[7] = new Timbre( sampleRate, 0.6 * loudnessPerTimbre, keyFrequency, heightPerTimbre, sin ); musicTimbres[8] = new Timbre( sampleRate, 0.4 * loudnessPerTimbre, keyFrequency, heightPerTimbre, sawWave ); // next, compute the longest note in the song int maxNoteLength = 0; for( y=0; y 0 || greenChannel[ imageIndex ] > 0 ) ) { currentNoteLength ++; } else { currentNoteLength = 0; } if( currentNoteLength > maxNoteLength ) { maxNoteLength = currentNoteLength; } } } printf( "Max note length in song = %d\n", maxNoteLength ); musicEnvelopes[0] = new Envelope( 0.02, 0.98, 0, 0, maxNoteLength, gridStepDurationInSamples ); musicEnvelopes[1] = new Envelope( 0.1, 0.9, 0.0, 0.0, maxNoteLength, gridStepDurationInSamples ); musicEnvelopes[2] = new Envelope( 0.5, 0.5, 0.0, 0.0, maxNoteLength, gridStepDurationInSamples ); musicEnvelopes[3] = new Envelope( 0.02, 0.98, 0.0, 0.0, maxNoteLength, gridStepDurationInSamples ); musicEnvelopes[4] = new Envelope( 0.9, 0.0, 1.0, 0.1, maxNoteLength, gridStepDurationInSamples ); musicEnvelopes[5] = new Envelope( 0.25, 0.5, 1.0, 0.25, maxNoteLength, gridStepDurationInSamples ); musicEnvelopes[6] = new Envelope( 0.25, 0.7, 1.0, 0.05, maxNoteLength, gridStepDurationInSamples ); musicEnvelopes[7] = new Envelope( 0.02, 0.98, 0.0, 0.0, maxNoteLength, gridStepDurationInSamples ); musicEnvelopes[8] = new Envelope( 0.1, 0.9, 0.0, 0.0, maxNoteLength, gridStepDurationInSamples ); noteGrid = new Note**[ h ]; for( int y=0; y 0 || greenChannel[ imageIndex ] > 0 ) ) { if( notePlaying ) { // part of note that's already playing // one more grid step noteStart->mDuration += gridStepDuration; noteStart->mNumSamples += gridStepDurationInSamples; } else { // start a new note noteGrid[y][x] = new Note(); noteGrid[y][x]->mScaleNoteNumber = noteNumber; noteGrid[y][x]->mTimbreNumber = y / ( heightPerTimbre + 1 ); // same as timbre number noteGrid[y][x]->mEnvelopeNumber = noteGrid[y][x]->mTimbreNumber; // left loudness from green brightness noteGrid[y][x]->mLoudnessLeft = greenChannel[ imageIndex ]; // right loudness from red brightness noteGrid[y][x]->mLoudnessRight = redChannel[ imageIndex ]; noteGrid[y][x]->mStartTime = gridStepDuration * x; // one grid step so far noteGrid[y][x]->mDuration = gridStepDuration; noteGrid[y][x]->mNumSamples = gridStepDurationInSamples; // track if it needs to be continued notePlaying = true; noteStart = noteGrid[y][x]; } } else { // no tone if( notePlaying ) { // stop it notePlaying = false; noteStart = NULL; } } } } } void startMusic( const char *inTGAFileName ) { loadMusicImage( inTGAFileName ); SDL_AudioSpec audioFormat; /* Set 16-bit stereo audio at 22Khz */ audioFormat.freq = sampleRate; audioFormat.format = AUDIO_S16; audioFormat.channels = 2; audioFormat.samples = 512; /* A good value for games */ audioFormat.callback = audioCallback; audioFormat.userdata = NULL; /* Open the audio device and start playing sound! */ if( SDL_OpenAudio( &audioFormat, NULL ) < 0 ) { printf( "Unable to open audio: %s\n", SDL_GetError() ); } // set pause to 0 to start audio SDL_PauseAudio(0); } void stopMusic() { SDL_CloseAudio(); if( musicImage != NULL ) { delete musicImage; musicImage = NULL; } for( int y=0; yisLookupDone() ) { mError = true; mNumericalAddress = mLookupThread->getResult(); if( mNumericalAddress != NULL ) { // use timeout of 0 for non-blocking // will be set to true if we time out while connecting char timedOut; mSock = SocketClient::connectToServer( mNumericalAddress, 0, &timedOut ); if( mSock != NULL ) { mError = false; } } if( mError ) { // lookup or socket construction failed return -1; } } else { // still looking up return 0; } } int connectStatus = mSock->isConnected(); if( connectStatus == 0 ) { // still trying to connect return 0; } else if( connectStatus < 0 ) { // failed to connect mError = true; return -1; } else if( connectStatus == 1 ) { // connected if( mRequestPosition < (int)( strlen( mRequest ) ) ) { // try to send more char *remainingRequest = &( mRequest[ mRequestPosition ] ); int numSent = mSock->send( (unsigned char *)remainingRequest, strlen( remainingRequest ), // non-blocking false ); if( numSent == -1 ) { mError = true; return -1; } if( numSent == -2 ) { return 0; } mRequestPosition += numSent; // don't start looking for response in same step, // even if we just sent the entire request // in practice, it's never ready that fast return 0; } else if( mResultReady ) { return 1; } else { // done sending request // still receiving response long bufferLength = 5000; unsigned char *buffer = new unsigned char[ bufferLength ]; // non-blocking // keep reading as long as we get full buffers int numRead = bufferLength; while( numRead > 0 ) { numRead = mSock->receive( buffer, bufferLength, 0 ); if( numRead > 0 ) { for( int i=0; igetFontColor()->copy(); mText->setFontColor( mHighlightColor.copy() ); } mText->drawText( mString, mAnchorX, mAnchorY, mWidth, mHeight ); if( mHighlightOn ) { mText->setFontColor( oldColor ); } } #endif between-6+dfsg1.orig/game7/gameSource/builderHint.png0000640000175000017500000000162711105754500021316 0ustar pabspabs‰PNG  IHDR‘h6PLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*RIDAT(ÏcdÈe 010ÐX o2n…¹˜&3àóL–r?LfÀ/Â„Ï ´ Vˆ'£!)¸r±ž Gg300000¢qŒƒ/ñ7 i„/ÖIEND®B`‚between-6+dfsg1.orig/game7/gameSource/musicPlayer.h0000640000175000017500000000050711377036601021007 0ustar pabspabs // starts playing music, reading notes from a TGA graphics file // the file must be in the "music" directory void startMusic( const char *inTGAFileName ); // set loudness in range [0.0,1.0] void setMusicLoudness( double inLoudness ); // causes music to jump back to beginning void restartMusic(); void stopMusic(); between-6+dfsg1.orig/game7/gameSource/target.png0000640000175000017500000000232411076176333020337 0ustar pabspabs‰PNG  IHDR0‘ ¬›PLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*IDATxÚíœÑnB!D™¦ÿÿËÓ§¦°¹»r­"‡Äá$3– QnMÝ«û¢õ½æý‡ÞRð[]ÎõÕÞ¬tÕ¾G{¸ÓX%OÄMçæ&B² =Ô ëNK÷¶qf†À7îêl; %€d¥Ö²~Í’=_ËÜæY5¤¦«­•äÐÎÊøfø«²³Ï „dÖÔ‹»º;|†d»{¨j§¨ƒd‡å‘  ä3F+¬¦nédŸ™CêdƒÐNJ „d›çPà›ñ.åMô,@Á…$Û0‡¬×Sð|hóµ¬XÓdŠêú>’5õC5ò3öÿH@çíËÜ6ëÉ € €zçz(>V¿¾+½49·?uoŸñ‡›ì$•ÏÞ‹3Ïð‘ì¬ZÉ$ûüzhá ÐÒ8H@¬e×ÉU½+$ €îM•'¯!@@ôßÍ¿/»¹¹ùÅiõ#˜ôojeIEND®B`‚between-6+dfsg1.orig/game7/gameSource/playMusic.cpp0000640000175000017500000000144111103622361021000 0ustar pabspabsint mainFunction( int inArgCount, char **inArgs ); int main( int inArgCount, char **inArgs ) { return mainFunction( inArgCount, inArgs ); } #include #include "musicPlayer.h" #include "minorGems/system/Thread.h" double musicTrackFadeLevel = 9 / 9.0; int mainFunction( int inArgCount, char **inArgs ) { setMusicLoudness( 1 ); if( inArgCount > 1 ) { startMusic( inArgs[1] ); } else { startMusic( "music.tga" ); } while( true ) { int number; int numRead = scanf( "%d", &number ); if( numRead == 1 && number >0 && number <=9 ) { musicTrackFadeLevel = number / 9.0; } //Thread::staticSleep( 1000 ); } } between-6+dfsg1.orig/game7/gameSource/World.h0000640000175000017500000000133411064753102017573 0ustar pabspabs#ifndef WORLD_INCLUDED #define WORLD_INCLUDED #include "minorGems/util/SimpleVector.h" #include "GameObject.h" class World { public: ~World(); // inObject will be destroyed when World is destroyed void add( GameObject *inObject ); // inObject is NOT destroyed by this call void remove( GameObject *inObject ); // draws all objects in the world // screen centered on world x position inScreenCenterX void draw( double inScreenCenterX ); // steps all objects in world void step(); protected: SimpleVector mObjects; }; #endif between-6+dfsg1.orig/game7/gameSource/morningTileVertical.png0000640000175000017500000000161611102637510023022 0ustar pabspabs‰PNG  IHDR‘h6PLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*IIDAT(ÏcPQQùÿŸxÄÄ@"±TUUIÓpûöm//¢uÀ#.7—¨ˆc@ŽéI“HÔðÿ?öm$jøÿŸáömÓ’ŠÊÀF<"˜¡@¼ûIEND®B`‚between-6+dfsg1.orig/game7/gameSource/Cloud.cpp0000640000175000017500000000425511103146352020107 0ustar pabspabs#include "Cloud.h" #include "common.h" #include "minorGems/util/random/StdRandomSource.h" extern StdRandomSource randSource; Cloud::Cloud() : mBaseFade( 1.0 ), mShiftA( NULL ), mShiftB( NULL ) { mXSpeed = randSource.getRandomBoundedDouble( 0.005, 0.001 ); } void Cloud::shiftBetween( Cloud *inA, Cloud *inB, int inNumSteps ) { mShiftA = inA; mShiftB = inB; mNumShiftSteps = inNumSteps; mNumShiftStepsDone = 0; } void Cloud::draw( double inRotation, Vector3D *inPosition, double inScale, double inFadeFactor, Color *inColor ) { if( mShiftA == NULL ) { GameObject::draw ( inRotation, inPosition, inScale, inFadeFactor, inColor ); } else { double bBlend = mNumShiftStepsDone / (double)mNumShiftSteps; double aBlend = 1 - bBlend; // draw A underneath, but don't use full blend, // because both A and be might be transparent mShiftA->draw( inRotation, inPosition, inScale, inFadeFactor * aBlend, inColor ); // fade B in on top mShiftB->draw( inRotation, inPosition, inScale, inFadeFactor * bBlend, inColor ); } } void Cloud::step() { if( mShiftA == NULL ) { mFadeFactor = mBaseFade; // can see the stepping, pixel, pixel, pixel //mX += mXSpeed; } else { // shifting mNumShiftStepsDone ++; if( mNumShiftStepsDone > mNumShiftSteps ) { // stop shifting mShiftA = NULL; mShiftB = NULL; } else { double bBlend = mNumShiftStepsDone / (double)mNumShiftSteps; bBlend = smoothBlend( bBlend ); double aBlend = 1 - bBlend; mX = mShiftA->mX * aBlend + mShiftB->mX * bBlend; mY = mShiftA->mY * aBlend + mShiftB->mY * bBlend; mFadeFactor = mShiftA->mFadeFactor * aBlend + mShiftB->mFadeFactor * bBlend; } } } between-6+dfsg1.orig/game7/gameSource/insertHint.png0000640000175000017500000000172511103077045021173 0ustar pabspabs‰PNG  IHDR øbêPLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*IDAT8˵“Ë À CI• ˜“¼0;ôP„øW%$DÀVx–Uˆ@†¿ÿb_¯ëÿÕ;2üŒ@3ÿ”¸}¨ãÂRÄ–²TpÔe(Ë5‹µš¤,V%ýv·u¬û”ð#ž'Ìíž]:L³å]Î{5ÓÔ†Ö<}MârDþ ÎŸd^à,EÒÙÜc““;¤âIEND®B`‚between-6+dfsg1.orig/game7/gameSource/blockBuilderTarget.png0000640000175000017500000000156311105754500022614 0ustar pabspabs‰PNG  IHDR‘h6PLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*.IDAT(ÏíÒ± 0Ä@“ÅãL+€”ëÛë>žÒë*jBsêaØ‚¿@Lï]ªB "¢àIEND®B`‚between-6+dfsg1.orig/game7/gameSource/GridTransition.h0000640000175000017500000000120111077534571021450 0ustar pabspabs#ifndef GRID_TRANSITION_INCLUDED #define GRID_TRANSITION_INCLUDED #include "BlockGrid.h" #include "BlendedBlock.h" #include "World.h" class GridTransition { public: GridTransition( BlockGrid *inA, BlockGrid *inB, World *inWorld, int inNumTransitionSteps ); // removes grid's blocks from inWorld ~GridTransition(); char isDone(); protected: World *mWorld; // used to check if blend done BlendedBlock *mFirstBlendedBlock; SimpleVector mBlocks; }; #endif between-6+dfsg1.orig/game7/gameSource/common.h0000640000175000017500000000102311377036601017774 0ustar pabspabs#ifndef COMMON_INCLUDED #define COMMON_INCLUDED #include "minorGems/graphics/Image.h" //#include // reads a TGA file from the default ("graphics") folder Image *readTGA( const char *inFileName ); Image *readTGA( const char *inFolderName, const char *inFileName ); // implemented in game.cpp Color codeToColor( char inCode ); // implemented in game.cpp void flipColorCodes( char *inColorSignature ); // maps linear values in [0,1] to smoothed [0,1] using sine double smoothBlend( double inValue ); #endif between-6+dfsg1.orig/game7/gameSource/nightTileCorner.png0000640000175000017500000000153211102170474022137 0ustar pabspabs‰PNG  IHDR‘h6PLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*IDAT(Ïc` ܾ}‡aŒ‚á iÊ“1Zê`IEND®B`‚between-6+dfsg1.orig/game7/gameSource/music.png0000640000175000017500000000325111103622361020155 0ustar pabspabs‰PNG  IHDR@†âº PLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*dIDATxÚí[]’¤ –GYïá‰<Œ—™WîáÞ%ûÀÐmÐD@`;T—•bèt>ó[™¼×Ê Û:?@çK(€o`ŒÙqº¤¥‹Ã3…¿8l!‚Ã̤Kó¤_3f3ƫϬ—tiþ£ß"VÅ ½áqérüÇ›®#¨ £ÕÃè>Jô·F@ü#±Î¿M-§Õ‰¿+‘¡]ÞN6w`/ô °”"å´‘?ÌeóÚ)×o Ë]{ý9‹¡3÷踘3ó0FKˆ¿iw ¯¥,øÚ´ö‡Ã~2BcKªaMdZNk9­åte'¶8Yß™±¸iºb竘Í6û^ÅlÖ MWìüFKklÌ'èB´´ÓØ+³Îæ~YãÏʧÙlîÙ ·-19 &×Xuþàäsæáhi¨À çä›Íz°lm«(-§µœî¥œÎVJ¤t×8ßÉÖ¥íG)Në2ÆŸ@Ú-ÝK¥ü×HrR‡,Ö-½kZaþh—\?vÿ3Ç>ækÿð¼ç”éü»ÏÚ•ÐZH(-§µœî; NÈk÷íg›qb:%x¥\0Z,ŽBRÀ@\‚ï,¶ÏÓCY ûw¶ßYlŸ¸´‰þæØôrâT3“Û£³Ó°S÷ÆÜ¿F÷Fž¯‚ª¹´{ï ?dï'²fßçvÏ1é!(ÜÉ—Ós÷ù€3sRÀ)!øs¿B5ÊÑXÓåt^ÕrZËim«( m•Þ1tþO>‹×£¾”®>¢uÌÄt )>êû¦[,þ7kk€‹—ÜÜôº°–ÓZNk9­ê;q‹ŽØ4¢Ñin,ìï‹QAÅòä sñk‰•fæb6Ç9ãÜØ+îĵÒ< ´+¡å´–ÓŸ)¥àó .÷zp6,[pÑ›K”¾FcøªÄA§  ôæRÊ-¦œNF QZ|Nô4áuÍól0”}CÍ…Q§„OÛÍhÓZÌ) å´–ÓÚþ'®ÖEŒ4ÎL'p3sþó¦»Ñ@\3“Hæ½pÙ~·Ý0êætý´îéÿY²ß¹ üSü$êÄn¾Ÿ:SÞÉZÊÿ¡<@'kó‚©ÈB`Ž&W÷vÓ 1†£I¤Äo-§×?áÔoÔø-KIEND®B`‚between-6+dfsg1.orig/game7/gameSource/morningTileCorner.png0000640000175000017500000000154611102637510022503 0ustar pabspabs‰PNG  IHDR‘h6PLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*!IDAT(ÏcPQQùÿŸxÄøÿ?I€‰aTè†!¢¼ü jŽ+#¥IEND®B`‚between-6+dfsg1.orig/game7/gameSource/morningTile.png0000640000175000017500000000162111102637510021324 0ustar pabspabs‰PNG  IHDR‘h6PLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*LIDAT(Ïíб À CQ“Yœa†e†eæSÒÂEN.,K¯¹b[ÑÁ!ö{Üá€j ¨µ€zhŒ€æÜ½@öÕGúÁ`TŠ»èÕýk`IEND®B`‚between-6+dfsg1.orig/game7/gameSource/Makefile.all0000640000175000017500000000721111377036601020547 0ustar pabspabs# # Modification History # # 2006-June-27 Jason Rohrer # Created. Copied from Transcend. # ## # The portion of game7 Makefiles common to all platforms. # # Should not be made manually---used by game7/configure to build Makefiles. ## ROOT_PATH = ../.. MUSIC_PLAYER_SOURCE = musicPlayer.cpp \ Timbre.cpp \ Envelope.cpp \ common.cpp \ playMusic.cpp LAYER_SOURCE = \ game.cpp \ common.cpp \ Sprite.cpp \ GameObject.cpp \ World.cpp \ Block.cpp \ BlockGrid.cpp \ TargetBlock.cpp \ BuilderTargetBlock.cpp \ WebRequest.cpp \ Client.cpp \ BlendedBlock.cpp \ GridTransition.cpp \ NightBackground.cpp \ Player.cpp \ Star.cpp \ Cloud.cpp \ musicPlayer.cpp \ Timbre.cpp \ Envelope.cpp \ LAYER_OBJECTS = ${LAYER_SOURCE:.cpp=.o} MUSIC_PLAYER_OBJECTS = ${MUSIC_PLAYER_SOURCE:.cpp=.o} GAME_GRAPHICS = \ graphics/tile.tga \ graphics/player.tga \ graphics/blockBase.tga \ graphics/blockNoise.tga \ graphics/selector.tga \ graphics/blockBuilder.tga \ graphics/blockBuilderTarget.tga \ graphics/builderHint.tga \ graphics/target.tga \ graphics/font.tga \ graphics/nightTile.tga \ graphics/nightTileVertical.tga \ graphics/nightTileCorner.tga \ graphics/bed.tga \ graphics/nightWindow.tga \ graphics/star.tga \ graphics/morningTile.tga \ graphics/morningTileVertical.tga \ graphics/morningTileCorner.tga \ graphics/alarmStand.tga \ graphics/morningWindow.tga \ graphics/backHint.tga \ graphics/nextHint.tga \ graphics/insertHint.tga \ graphics/upHint.tga \ graphics/downHint.tga \ graphics/clouds.tga \ music/music.tga \ NEEDED_MINOR_GEMS_OBJECTS = \ ${SCREEN_GL_SDL_O} \ ${SINGLE_TEXTURE_GL_O} \ ${TYPE_IO_O} \ ${STRING_UTILS_O} \ ${STRING_BUFFER_OUTPUT_STREAM_O} \ ${PATH_O} \ ${TIME_O} \ ${THREAD_O} \ ${MUTEX_LOCK_O} \ ${APP_LOG_O} \ ${PRINT_LOG_O} \ ${LOG_O} \ ${PRINT_UTILS_O} \ ${TRANSLATION_MANAGER_O} \ ${SOCKET_O} \ ${HOST_ADDRESS_O} \ ${SOCKET_CLIENT_O} \ ${NETWORK_FUNCTION_LOCKS_O} \ ${LOOKUP_THREAD_O} \ ${SETTINGS_MANAGER_O} \ ${FINISHED_SIGNAL_THREAD_O} \ ${SHA1_O} \ ${ENCODING_UTILS_O} \ TEST_SOURCE = TEST_OBJECTS = ${TEST_SOURCE:.cpp=.o} DEPENDENCY_FILE = Makefile.dependencies # targets all: Between ${GAME_GRAPHICS} clean: rm -f ${DEPENDENCY_FILE} ${LAYER_OBJECTS} ${TEST_OBJECTS} ${NEEDED_MINOR_GEMS_OBJECTS} Between ${GAME_GRAPHICS} Between: ${LAYER_OBJECTS} ${NEEDED_MINOR_GEMS_OBJECTS} ${EXE_LINK} -o Between ${LAYER_OBJECTS} ${NEEDED_MINOR_GEMS_OBJECTS} ${PLATFORM_LINK_FLAGS} # add this on Unix to support JPEG video frame output # -ljpeg ${ROOT_PATH}/minorGems/graphics/converters/unix/JPEGImageConverterUnix.cpp playMusic: ${MUSIC_PLAYER_OBJECTS} ${NEEDED_MINOR_GEMS_OBJECTS} music/music.tga ${EXE_LINK} -o playMusic ${MUSIC_PLAYER_OBJECTS} ${NEEDED_MINOR_GEMS_OBJECTS} ${PLATFORM_LINK_FLAGS} # sed command for fixing up the dependencies generated by g++ # g++ (pre-3.0) leaves the path off of the .o target # look for a .o file at the beginning of a line (in other words, one # without a path), and replace it with the full-path version. # This should be compatible with g++ 3.0, since we only replace .o names # that occur at the beginning of a line (using the "^" modifier) GAME_7_SED_FIX_COMMAND = sed ' \ ' # build the dependency file ${DEPENDENCY_FILE}: ${LAYER_SOURCE} ${TEST_SOURCE} rm -f ${DEPENDENCY_FILE} ${COMPILE} -MM ${LAYER_SOURCE} ${TEST_SOURCE} >> ${DEPENDENCY_FILE}.temp cat ${DEPENDENCY_FILE}.temp | ${GAME_7_SED_FIX_COMMAND} >> ${DEPENDENCY_FILE} rm -f ${DEPENDENCY_FILE}.temp include ${DEPENDENCY_FILE} # # Generic: # # Map all png files into .tga files # # $@ represents the name.tga file # $< represents the name.png file # graphics/%.tga: %.png convert $< $@ music/%.tga: %.png convert $< $@ between-6+dfsg1.orig/game7/gameSource/morningWindow.png0000640000175000017500000000213511102637510021677 0ustar pabspabs‰PNG  IHDR üí£PLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*IDATHÇíVËÄ EÇV¶Ó‹C1±˜ÃüÄñf³;{ ‡D}ÀP~*à1À‹©?ðõPL ±B8kÇ@qª^)D×5Jb¤ÙÒ,6—B&$P^­Súï, œ£èx‹BHÎÏÞ…ú®`Wµ±[„þÈŒgèZW^ùCHÍ£óÎÆ)Þ†îq :!Ìô’¹"¤b£·¤g%ö KÒÌ s¾l4b;k_Ój—³¨”Õ¥)Ù€µ©PÓ1l]®õ8Ÿ/GPR(9›¡‹ïbAè~êqösé>°$ÏÏj7½tªÏ¥ëÒÊÍ—€l€O±q±m-ö¾ÙãÃ4—;vŠÌ!»E=_IÞ¥'‘eN<IEND®B`‚between-6+dfsg1.orig/game7/gameSource/nightWindow.png0000640000175000017500000000204011102230144021322 0ustar pabspabs‰PNG  IHDR üí£PLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*ÛIDATHÇíVÁà Ã\VÉxõ0Z/Ã$zÔÆ`J¯yÄ/r Cá~1„ÀŽM~`Ç’¤|°ðA˜98ý’3ë9$«;ê\ê2¹•z~ŸAÙ+é¿«¨à[3³•(ljó}tL ÛOÙ‰Ifï’ˆÞì^¡¢Z”¶ôF[›1°fÉ­å0ÆI¨õù ©Ÿ«hFÍŒ±}·ÆËÿWE­’ëxŸž|˦?ݶ¾0‹d²áÈkkðîk=>¨x›&Aøà<Ô°µ„žÇo/.@~œ wÃIEND®B`‚between-6+dfsg1.orig/game7/gameSource/languages/0000750000175000017500000000000011435543353020306 5ustar pabspabsbetween-6+dfsg1.orig/game7/gameSource/languages/English.txt0000640000175000017500000000114611211107726022433 0ustar pabspabstitle "Between" initialRequest "Locating server..." createForFriend "Create a new game for a friend to join." joinWithFriend "Join a game that a friend has started." joinWithStranger "Join a game with a stranger. " creatingGame "Creating a new game..." waitingForFriend "Waiting for your friend to enter the following code:" waitingForStranger "Waiting for a stranger to join with..." enterCode "Ask your friend for a code and enter it here:" joiningWithFriend "Joining the game..." otherSilent "Other has been silent for #VAR minutes." quitQuestion "Really quit? Press Y or N"between-6+dfsg1.orig/game7/gameSource/Player.cpp0000640000175000017500000000715011377036601020302 0ustar pabspabs#include "Player.h" #include "common.h" Player::Player() : mShiftingPosition( false ) { const char *imageFileName = "player.tga"; mSprite = new Sprite( imageFileName, true, 16, 4 ); Image *spriteImage = readTGA( imageFileName ); Image *whiteImage = spriteImage->copy(); Image *brownImage = spriteImage->copy(); // change all black pixels to white or light brown Color black( 0, 0, 0 ); Color white( 1, 1, 1 ); Color lightBrown( 191.0/255, 136.0/255, 0 ); // change all dark grey pixels to light gray or dark brown Color darkGrey( 54.0/255, 54.0/255, 54.0/255 ); Color lightGrey( 182.0/255, 182.0/255, 182.0/255 ); Color darkBrown( 141.0/255, 100.0/255, 0 ); int w = spriteImage->getWidth(); int h = spriteImage->getHeight(); int numPixels = w * h; for( int i=0; igetColor( i ); if( c.equals( &black ) ) { whiteImage->setColor( i, white ); brownImage->setColor( i, lightBrown ); } else if( c.equals( &darkGrey ) ) { whiteImage->setColor( i, lightGrey ); brownImage->setColor( i, darkBrown ); } } mWhiteSprite = new Sprite( whiteImage, true, 16, 4 ); mBrownSprite = new Sprite( brownImage, true, 16, 4 ); delete whiteImage; delete brownImage; delete spriteImage; mSprites[0] = mSprite; mSprites[1] = mWhiteSprite; mSprites[2] = mBrownSprite; } Player::~Player() { delete mSprite; delete mWhiteSprite; delete mBrownSprite; } void Player::shiftPosition( double inNewX, int inNumSteps ) { mShiftingPosition = true; mShiftPositionA = mX; mShiftPositionB = inNewX; mNumShiftPositionSteps = inNumSteps; mNumShiftPositionStepsDone = 0; } void Player::step() { if( mShiftingPosition ) { mNumShiftPositionStepsDone ++; if( mNumShiftPositionStepsDone > mNumShiftPositionSteps ) { mShiftingPosition = false; } else { double bBlend = mNumShiftPositionStepsDone / (double)mNumShiftPositionSteps; bBlend = smoothBlend( bBlend ); double aBlend = 1 - bBlend; mX = mShiftPositionA * aBlend + mShiftPositionB * bBlend; } } } void Player::draw( double inRotation, Vector3D *inPosition, double inScale, double inFadeFactor, Color *inColor ) { if( mX > -26.5 && mX < 24.5 ) { mSprite->draw( mSpriteFrame, inRotation, inPosition, inScale, inFadeFactor, inColor ); } if( mX < -22.5 ) { // fade in white sprite on top double fade = ( mX - (-22.5) ) / ( -26.5 - (-22.5) ); if( fade > 1 ) { fade = 1; } mWhiteSprite->draw( mSpriteFrame, inRotation, inPosition, inScale, fade * inFadeFactor, inColor ); } if( mX > 20.5 ) { // fade in brown sprite on top double fade = ( mX - 20.5 ) / ( 24.5 - 20.5 ); if( fade > 1 ) { fade = 1; } mBrownSprite->draw( mSpriteFrame, inRotation, inPosition, inScale, fade * inFadeFactor, inColor ); } } between-6+dfsg1.orig/game7/gameSource/BuilderTargetBlock.cpp0000640000175000017500000000060511105745601022550 0ustar pabspabs #include "BuilderTargetBlock.h" #include "minorGems/util/random/StdRandomSource.h" extern StdRandomSource randSource; BuilderTargetBlock::BuilderTargetBlock( Sprite *inSprite, int inShimmerTime ) : TargetBlock( inSprite, "256A", inShimmerTime ) { } BuilderTargetBlock *BuilderTargetBlock::copy() { return new BuilderTargetBlock( mSprite, mShimmerTime ); } between-6+dfsg1.orig/game7/gameSource/Sprite.h0000640000175000017500000000417311377036601017763 0ustar pabspabs#ifndef SPRITE_INCLUDED #define SPRITE_INCLUDED #include "minorGems/graphics/openGL/SingleTextureGL.h" #include "minorGems/graphics/Color.h" #include "minorGems/math/geometry/Vector3D.h" #include class Sprite{ public: // transparent color for RGB images can be taken from lower-left // corner pixel // lower-left corner ignored for RGBA images // image split vertically into inNumFrames of equal size Sprite( const char *inImageFileName, char inTransparentLowerLeftCorner = false, int inNumFrames = 1, int inNumPages = 1 ); Sprite( Image *inImage, char inTransparentLowerLeftCorner = false, int inNumFrames = 1, int inNumPages = 1 ); ~Sprite(); void draw( int inFrame, double inRotation, Vector3D *inPosition, double inScale = 1, double inFadeFactor = 1, Color *inColor = NULL ); int getNumFrames() { return mNumFrames; } void setFlipHorizontal( char inFlip ) { mFlipHorizontal = inFlip; } // used to adjust horizontal center point, in pixels void setHorizontalOffset( double inOffset ) { mHorizontalOffset = inOffset; } void setPage( int inPage ) { mCurrentPage = inPage; } int getPage() { return mCurrentPage; } protected: SingleTextureGL *mTexture; int mNumFrames; int mNumPages; double mBaseScaleX; double mBaseScaleY; char mFlipHorizontal; double mHorizontalOffset; int mCurrentPage; void initTexture( Image *inImage, char inTransparentLowerLeftCorner = false, int inNumFrames = 1, int inNumPages = 1 ); }; #endif between-6+dfsg1.orig/game7/gameSource/cloudsBase.png0000640000175000017500000000570611103140044021121 0ustar pabspabs‰PNG  IHDR @ôìâùPLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*IDATXÃM˜[ŽÜ: Dm‰–ß ™ìÙTÈs»Û¶d½îÇq8íÁ´Y,Iµ?~üðÞßï÷Çãὑoß¾}ÿþ}š&ïýqÖZç\­õ<ÏRJÓ4"²®ë<Ï1Æ¿ÿ>ŸOçÜ0 )¥œ³1¦ÖšsÎ9—R¤ÖÚ¶­®b­5Æ”RXËZÛ¶mÎ9¥tžgÓ4ú”嚦išF–RX¤ë:cLÎYš¦iÛ–ÕsìÄÆ)¥œç¹ï»÷ÞZ+"}ߟçiŒI)•RXˆ;µVÌrÎa–äœk­<àã¾ïÛ¶­µ²AŒ1ÆxG;mÛÆk­1FÅÍÇMÓt]ÇkmÛÊý~ÇÞZë0 l€ƒMÓÔZñZDøÉó<ÏóŒ1‚R×uιi𬵼Æùýû·1Æ97Ž#«;ç0D7æf­Õ{¿ï{ŒÑ{¬B• !¾êºN¶m‘®ëøÝ¶m!¥¤Ñnšf‚QkÝ÷§¼Ï'xÀÓÇã±ï»ˆ€§¬ëÚuݺ®ã8ŠÈyž÷ûÝ{¿,˺®&)¥cÛ¶„j†®ë¬µ¯”â½>ŸÇq@&ooo"2MÓ8ŽÖÚ}ß÷}?Ž«»®S yïcŒÖZ’€07«oÛB€BàœR˜DÖÚ”Ò0 ¥2 mÛRJáù|nÛcœ¦i]צiRJD”ÎóôÞ×Z‰e­•÷å8ŽRÊ8Žd\ß÷·ÛMDD„ï¹…à;é­d…£ä0æ†ÇÿýBMEMÂišŒ1˜Ïê|9Ž#ô…©"‚ÇšÆÄ¦”r¿ßÿüùó|>SJBö¦”¾a0P7V æEqΩ5ÖZk-69ç@RØ_cÂK¢“/}ßCÍ®ëJ)$?w4ž;Ýn·q1ÆÙ÷"7MC¢YkcŒ!ÔÍ9§hh&«<6–Ë9ÇSJmÛÎóŒ¡B®ƒþ¾ï¸B8Žã„€l!aš–8ctÿ.4‘€ªKö#Ðì*#mÛ’Àd)F%Á›œ³®¥>õ}¯Å]m' ZÉ…TZ–Ek>)åMꌲ½÷xâÐå¿ôƒ¨‚ÞášâC$5Q‰Dß÷TC­HÀ@D©”"Û¶©.’®]ƒŽ`B®€»jr”s>Žã8ç¼ÇJcŒhf©ê³ê+@¥” ®â[JQ³qž’=|+˲Ð"Üïwƒ2 £ÕAöSøèÃ@Ÿšˆh’Ã%¹ÝnÛ¶=°êºâ UâäœC+8ÃWÖÚaÈžÊqµiÔ<ê%Ò¨r¯])Ì‹š7à£ðÒ°°ÙU—B9ç¾ïÁŠuÉ8Ê!Ôñ•<ø‡£| (*—+ˆþº®TmMãצ£‰Z½»®£¹ÓHðŽÖ«”’Ç¡Ú TÁúï‘q‰9D|]ˆu5”!Ú!n2ÒÌ"†T˜RʶmçyÒ¨iŽù¯mkøw]rMûÁa'DਚX ñcŒÀSU‹ð镾—¨ÀH.Ä$ÆHc„ÝÓ4Á"õ §ù© d¿Ö*Ø’R:ޱÜ÷}Û6Þ¶íq¯ôg%¡Û `:†(¡5!æi÷ 1ˆ¤j¤J²Œ*¨ú²ñkýѾísFSRkÞNÓD`ThcŒZÖÁÄ1Ÿí)™¥”¾ï1BÉÕglŸ¦ ÿTût#­ ;šˆë ­íšµVbü:0V‡‹ªšä0¹­#ªÐ Ä{üŸu]aDTð0ÐFè8†´"t[tt¾wÎQoñ=„p¿ßÕ³×\ÕÎÎ3MiKÌ ‹|ùòE'>PJh£ µLÿå‘«eY ¨Î Wƒ¥ýúë¨CA¯µ20áÅÆíàIfºMEO>>>p j;Î$Ã0¦È¹ŒôH(3lD6.iÛV~þüÉX€²ÒŽ A¯¨g Þ{X‘Hˆ øÄßß߉;ñÑQ‡‹^ý\Œèûþñx`yJÌ`ˆ‘"µÖ+³°HO#° ÛñUeuÎis¯} j-¹ ÎÛÛ&`;½›úq—e™ç™sžî ˜¯&íÏÃF5|ä(U QsÎó<íŽÈŽö/ªn8—Rb{Ôûsj$¹Œ1Û¶q“pmÛ¦gO((RÊ êeþ\2ÇqÅyžd2~íûNµ›¦‰Ì,¥0ñR·!!mš†Á@àç,0[xÀþúMž.Ë>E: c©¯˜¬£íû~LÝn7à‹1nÛÆq‰÷ž–VDiô@½ä$VÇcéiD™Yäv»ñÙ¾ïÏçóŽC»`Æ! ísÎY¾~ýªÝ²váŠþë´ÉÀEòÁÐ’ð\ÁÀ®¦i8¿I)Íó¬]¢|t¬ÔùP:8£çÌ ×¤1Ðm˜T?´³ÓþLÏ*´…fŠî딈üI(˜¤¸ÊR=IEND®B`‚between-6+dfsg1.orig/game7/gameSource/bed.png0000640000175000017500000000213411102230144017557 0ustar pabspabs‰PNG  IHDR@ -ÿéÓPLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*IDATXÃíW[ƒ ¤WñxÝÃäz^¦AyÚB¢Xùr˜ f ›Í¾ÌÛô]4Sr ŒÀ²Ý³'J †É ¾¬ÜÑ€»ï\M¤l¸¥âDó®<¡ö€­ª8û.†6¸úŸI¬C€þ°€0²É%z‚M(Á¤ÄI^Mcec÷åXU†æþcõ=Šr—lÀ©ûÔaòaä,Øù’öÊuƒÕ^,˜»ø®…Y2.Îõ*PKNaÜ¿z<IÜ‹£|ŽP¿²-Ö„f*{_7±b¬N-ˆ¬ºçò=6š§œ¤°}‘¹ý §÷ÝÙñ)ùÛ”uÓ.t‰=˜ÕÛ†¦G™Õ¦IEND®B`‚between-6+dfsg1.orig/game7/gameSource/Timbre.h0000640000175000017500000000207711103404573017732 0ustar pabspabs #include class Timbre { public: /** * Constructs a timbre and fills its wavetables. * * @param inSampleRate number of samples per second. * @param inLoudness a scale factor in [0,1]. * @param inBaseFrequency the lowest note in the wave table, in Hz. * This is also the key for the major scale held in the wave table. * @param inNumWaveTableEntries the number of wavetable entries. * @param inWaveFunction a function mapping a double parameter t * to a wave height in [-1,1]. Must have a period of 2pi. */ Timbre( int inSampleRate, double inLoudness, double inBaseFrequency, int inNumWaveTableEntries, double( *inWaveFunction )( double ) ); ~Timbre(); int mNumWaveTableEntries; // mWaveTable[x] corresponds to a wave with frequency of // getFrequency(x) Sint16 **mWaveTable; int *mWaveTableLengths; }; between-6+dfsg1.orig/game7/gameSource/backHint.png0000640000175000017500000000164411103077045020567 0ustar pabspabs‰PNG  IHDR‘h6PLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*_IDAT(ÏÅ’ADÓëÎésaw°#$YùK5š‘D…:È Ôq.º[&*1="æ}»“ŸL£ÂŒ$'Óÿ&ˆÿê;éuq“ ;{ œͰè× × l¬ÌÍÐu0!ç €IEND®B`‚between-6+dfsg1.orig/game7/gameSource/blockBase.png0000640000175000017500000000212411076154456020736 0ustar pabspabs‰PNG  IHDR@œ`ÁPLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*IDATHÇå–A–„ D‹~ÅË»$‡Á»$ÇË,°iÇÑÝN× !è#¯>epÀT±V"*ƒn)EaÎ)uj]Z/ sÄ–ÒðŠªNêÞD$Ïóé/Äã¥9g¹äÐyžEä}m%"z:·(8@¿[MÍШYðÁÒ;JD±–îXºåáÀÌŽT/‡æœó·ðp@÷&®:VßPÕ:®Zß—1NÊ|¨ùP2a „––DfvwwWUUõµô©òÈm>l"1N~ÁEvKà“º´ðp¤K…išþ·–„@-{mX; Vector3D corners[4]; // first, set up corners relative to 0,0 corners[0].mX = - xRadius; corners[0].mY = - yRadius; corners[0].mZ = 0; corners[1].mX = xRadius; corners[1].mY = - yRadius; corners[1].mZ = 0; corners[2].mX = xRadius; corners[2].mY = yRadius; corners[2].mZ = 0; corners[3].mX = - xRadius; corners[3].mY = yRadius; corners[3].mZ = 0; int i; // add inPosition so that center is at inPosition for( i=0; i<4; i++ ) { corners[i].add( inPosition ); } int numStripes = 7; Vector3D stripeOffset( mDirection * 2 * xRadius, 0, 0 ); glBegin( GL_QUADS ); { for( int s=1; sdraw( mSpriteFrame, inRotation, inPosition, inScale, inFadeFactor, inColor ); } else { int oldPage = mSprite->getPage(); double bBlend = mNumShiftStepsDone / (double)mNumShiftSteps; bBlend = smoothBlend( bBlend ); // draw A at full blend mSprite->setPage( mShiftPageA ); mSprite->draw( mSpriteFrame, inRotation, inPosition, inScale, inFadeFactor, inColor ); // fade B in on top mSprite->setPage( mShiftPageB ); mSprite->draw( mSpriteFrame, inRotation, inPosition, inScale, inFadeFactor * bBlend, inColor ); // restore page mSprite->setPage( oldPage ); } } void GameObject::mainStep() { if( mShiftingPages ) { mNumShiftStepsDone ++; if( mNumShiftStepsDone > mNumShiftSteps ) { mShiftingPages = false; } } // call child's step function step(); } between-6+dfsg1.orig/game7/gameSource/clouds.png0000640000175000017500000001106611103140044020322 0ustar pabspabs‰PNG  IHDR @{Žu®bKGDÿÿÿ ½§“ pHYs  šœtIMEØ >EaÃIDAThÞ]yëo%ÇuçyUU÷å½—¢8ö̈;‘ì 23 "ÔZ'@D>! 2s‘šs·Û­ÞÝÝAÎùˆîO˲™ewÏÌüîb±"Dü&"ž¹û¯ˆhËÌ«¾ïŸ„Ή(¸û=¬Š3CkmžWÕ*"7)¥gföb³Ù|ôâÅ‹¿Úív—­µ&1Æã‡¦:Õãu×uï2³"â-<6³k3{*"×!„Ç)¥o‹È7Ìì|*ˆ19""Þ0óûÌü}wÿobŒ¿\­V7 2ÏøK ]×Õ®ë®E䇪úQkm[f¾J)íZk¯0óMáÆÌž¨ª¸ûql§FsDlªúÌ̾ˆï#âÍz½®}ßW"2"9óÌ@J RJÀ̵ÖúqÎù¶”B`1Æ*"ÆÌ‡ÖÚÜýCw?5323œêˆ)%ïûÞˆèNUŸÕZoZkáäädÆU¡˜‡0303äœm†\J‘¹]rÎõp8|ÌÌ·1Fš>fî>OÇAD ªªÚ j"rÄ éºfJPU¨µ7¥ªÐZD<6ׄ–RÊ]×3Ã܈3bÖZa†ãgÌì¸øôPJ9999ê D îNsYú¾°û1o ªbfÄÌB¨!›yê'BÄ "ÔZƒqÁÌŒˆjÁæ–R@UAÖëõŒ÷”s>Ë9¿Qk=cfšºÚDdSk}>© Çˆ¸L)mû¾¿J)Ýu]g"µV€S¸@ĵ™Ñ0 ÖZ» !|ØZ»Í9"‚ªÞo ë: "PÕPk}#çüßbŒ_EÄÄÌ ª ®ñƒ ßbæ‡1ÆëÅbñt¹\^¦”š»CkMÜýÞv÷ U•Zkn­ý„ˆ¾kf;UÍ"r$-™ë>Ž#åœÏàMùV¡ŸNƘy#"ïäœ×Z—1ÆmŒñíãˆÌ‘à/Ü}­ªdfƒ»3¼çîÿ6õDåœÌ͆ˆ¼X,õ)¥…ˆô€fæ°!<˜NDT•qéîTÕfž˜(™T5L‹±™=VÕ¯‘…®ñ—ªz×Z3`f^.—§"r§ÓŽQUÑÝq1~¹vµVÇ‘_­iƒ0Ž#”RÐÌ<„ñuwÿSfþrß÷?‘mkm«ª&¥JáµÂÛî~ÑZ“T˜Dä(Íæ’™Ù9‹¤”Žã71àD\gˆø¥ÂÐ÷}M)ìþd¿ß"R­uéî˜9̈…ˆ<ëÂyÌæãžqc†ð fcU…apŽ1†“““‚ˆ/`w„âi·æîfþYJ)¹û#wÏÌŒ'„Ãy†[k0ÏÌûó©Ìt<Óó d“ÒÃY7̈)ËåJ)µ”òáf³ùná=D|“™ÿ„ˆ~WUûZk@D&¢ãñÎpÚ÷ý‘M'eükÈ7—FDÈÝ×föš™­[kƒ™©¬×kØï÷¶Ýno÷ûýB¸=999íºî33{ØZ{™O' nÌ !ˆ1R¸g1šx£©ª!¢…Œ™©ëº™s˜ÙWEäï‰è…»«¤” ”ˆh¥”ÜZ«]×ý¬ïûLDïŠÈ›"òG1Æ wÿ¤”²13bæS3{MUWã8îrÎÏÀ˜yˆ[f>¤”Vîþ(çìîþKfÞt]§G“sU…”Lå0¹‘]Jé"r‹ˆ'1Ƶ™ýDU¯rέë: !\ÀÛµÖ‡µÖkøGfnîþjkícf¾‘‡"òÖÔ¯O»®ûI×uÏ ™ÈgŸ}1FX­V0Ž#¸»1s&¢ÊÌ?CÄ3sŒñ¹»oBB f>€§î¾BÄ]JéyÁj­ UÝšÙÁÌVDôw“\."·ªš[kÖZ†á×øy·IV™»ßºûÖÝADZß÷6Sö0 ‡ã "¢©ÞMDüžüÈ&ÝÀ'ˆDÔj­–s>Êz‰1BaVAÐ÷=Ì"eSÕBDc<êýý~¥[­VyjÈ—-ºÍº`RÓe–ôóg×#"BDDªjã8Öœ³åœ¡Ö ¥”_s;fFµÖPk¥©$µµfóϸ0Ÿêÿ?¦Gïº&Mwffo âÚÝwµÖ«ív{w8¬Öêómfãîï´Ö¸ÖúÄÌÖS„³035³Ç¥”u)…ˆ¨¨ê93ßÑykmÈ9ß™Ù/SJ7DÔ¤”2ÓÚ™ÿuòî§pBX‡h±Xà¤fföÀÌ@U¥”ÂDt&"+U•ÖMÖÕZ¿TkM­µ?h­eø™ÿ<¥ô3ßÈT×"þ+""3/Bˆ¸J)­RJ("3‹Í"…_6£ÀªÊ9ç—uÞ35ž•RVµVeæÒuÝ£ÅbñlŠneG"¢eá‹DôCK3{…™OW«MSD ›Í”R°”Dt -æeö³;ffžt…Çi$/q&1FŸüÜ¿hf L¹¥”PU!ç ˆ9gØl6³ý‚”Ì4=#ÜœLhŠ‹ÅÂcŒBC7îþ¼Öz/ÉNOOUDž‡>(¥¼3Žã…»Ç{FEð{>¾ÕËJèå¿gU4+#™}¢Çm¹\Þ1óÏàŸK)ŸÔZ›ª‚ˆˆŠÈ-3ÿÿ ‡¥”3SkÍÆq¬¥s÷c3'¨SÄGÓiXß÷ÕÝmz{@D!4f¾BÄ÷ZkÙZ{æîîÙ0„CÿVkýß½c|W¥”í0 WÃ0Ü1³õ})%h­Q)åtÇ‹ZëzâŠMŒñRD3€RŠ€©ê™ý¼”ò¡ªÞ‰ˆ!"Èåå%Ä­ëºDük"úUJé+­µ¯»ûÃZëu­õi)åRDÚl«Ý]bŒÌüö8ŽSŸ\2óÓ”Òeß÷MU¡”âT"º1³k¨G.¸¹¹#ô}_cŒ‡îZkæœ?`æ3ÏÁÄݤdˆPD(ÆxÊÌÿRZo·[¨µnj­—î~7¥#>”0QSU›§EæQšÞÀrÎå)ס¾ïMDj×u6¥'@Dsªr‘fF1Fh­"ÖÖš½lñg&œBëãÿZk <D$D”)'jã83çY·Í:a¹\ÂÉÉ ¸;Œã“ª©î~¼˜©µÎ¦÷ˆ ³åŸóDDY­VgˆøÄÝiÇ«ÃápcfuìÂÉÉ õ}Üj­8ù¿SU}mJζÌ|ÕZ»swSUŸŒŠ™Ym­OqöbfBDODäcŒ¯¤”~LD³ßïo̬Q›.î÷û³ÖÚ…ªž‡.Zko‡Ñ5=u÷ËZk›úŘù®”òLUoRJuö’DRJé*æ•Â;"òàp8œåœŸ•R>],ϋğ˜ÙWv»Ý×[k“*fD<%¢×Ü}UJÙÀÛã8ÞMÜLÊJ)áîRú¸ï{K)Ý»+DlDtED?Fĵª^”Rþûv»­ûýþªµöAŒ–Ëåêûþ+îþº™†(ƈîNªÜZkKU}0Ž£MRßcŒÆÌŸL¶ý¹ªÞ‡îûa½^"ÞŠÈÿ©µ>Úï÷'»Ýî?Ãðùq÷1Æw&È|¼\.ÏÒ½6£);8Ö“Âá™)gVœ ˜™ù­ÖÚ[¥”«ÍfsUk­1ÆûŒhú¢þp8|a·ÛýN)ås]×­SJëÕjõ¹É~ËdÅp¥ør*6óÀÌ /ó‚ª&3ûb­õ;‡Ãá.çüîf³¹fæ*s:æîKx]D¾°\.OW«Ç!¥ÄSÞî9gœ•ïü–óˆèós/ß´”R¸Öúê8Žÿeâ•ÜZ{×Ýo¤Ö ­5SÕ]áz¹\n‹ÅZD˜ˆpö³™‘m^ü¥;Ÿ6£fÖ&k.ªJÓHÂ$ϾrrròÛ­µj­ÝÊÍÍ ˜YEÄg)¥ï‹È93ÿþtMÇs;‡–ˆès`1¿ùŒˆXcŒ/ñr*Ed™R:ˆÈŽˆlEä…ªîTÕäêê ˜Ù‹Å ½Bx%„ð8„°€“é~hÖà÷çkˆX™Ù¦î—q ®ñGDôC"Òã[1ƇÌüiáwÿ­µLDÿîî[0)¥ÌAu‘SJt]÷Þ”||AUOsÎTJÁZë¼ø.§ iUJyTJiˆø~kíˆÈû€ýˆ¬ˆèÀÌ#½¯Nmp?"‹Åº®Ë}ßÿ¼ëºïÑ¿˜Ù×'ä“Z+–R¼µÖ˜ù²ëº§ˆxs~˜s~«µ¦"òÃa~B¸ff‘k­„ˆ¦ªÀÌ—1Æ%}6Ý!ƒ¼úê«@D³‡33»5³ˆè|àJªŠÓõŒ1óÆÌ.‰hÛZ[©êßM=r™s¾i­ÕéºNçÆFöocŒ6¹ç{o8Ïî0 PJ±ÖÚprr’™ùfŠ[ˆ|ò6%i&"»ã'“nlS¶ðkL8'æªj"b]×iýxy='Ø3ˆ¤”æâx 1ŸÔ<çÓ³–R*3Ç¿ì|ç ÔZŒúòÝ„ˆÐÿóIQ„~eIEND®B`‚between-6+dfsg1.orig/game7/gameSource/Client.cpp0000640000175000017500000005574111377036601020275 0ustar pabspabs #include "Client.h" #include "common.h" #include "minorGems/util/stringUtils.h" #include "minorGems/util/SettingsManager.h" #include char *Client::sServerURL = NULL; void Client::staticFree() { if( sServerURL != NULL ) { delete [] sServerURL; sServerURL = NULL; } } Client::Client() : mPlayerID( NULL ), mGameID( NULL ), mGamePasscode( NULL ), mPlayerNumber( NULL ), mGameReady( false ), mTimeLastCheckedReady( 0 ), // every 5 seconds mTimeBetweenChecks( 5 ), mTimeLastReportedAlive( 0 ), // every 5 minutes mTimeBetweenReports( 300 ), mSecondsSincePartnerActed( 0 ), mLastStateSeen( stringDuplicate( "0" ) ), mGridToUpdate( NULL ), mError( false ), mErrorString( NULL ), mCurrentType( NONE ), mCurrentRequest( NULL ) { // default transform for( int i=0; i<16; i++ ) { mBlockTransform[i] = i; } mServerFinderURL = SettingsManager::getStringSetting( "serverFinderURL" ); if( mServerFinderURL != NULL ) { if( sServerURL == NULL ) { QueuedRequest *q = new QueuedRequest( GET_SERVER_URL, "GET", mServerFinderURL, NULL ); mQueuedRequests.push_back( q ); step(); } } else { setError( "ERROR: No serverFinderURL in settings folder." ); } mPlayerID = SettingsManager::getStringSetting( "playerID" ); if( sServerURL != NULL && mPlayerID == NULL ) { // request an ID QueuedRequest *q = new QueuedRequest( GET_ID, "POST", sServerURL, "action=get_player_id" ); mQueuedRequests.push_back( q ); } } Client::~Client() { if( mServerFinderURL != NULL ) { delete [] mServerFinderURL; } if( mCurrentRequest != NULL ) { delete mCurrentRequest; } if( mPlayerID != NULL ) { delete [] mPlayerID; } if( mGameID != NULL ) { delete [] mGameID; } if( mGamePasscode != NULL ) { delete [] mGamePasscode; } if( mPlayerNumber != NULL ) { delete [] mPlayerNumber; } delete [] mLastStateSeen; if( mErrorString != NULL ) { delete [] mErrorString; } for( int i=0; i mTimeBetweenChecks ) { mTimeLastCheckedReady = curTime; char *actionString = autoSprintf( "action=is_partner_ready" "&game_id=%s" "&game_passcode=%s" "&player_number=%s", mGameID, mGamePasscode, mPlayerNumber ); QueuedRequest *q = new QueuedRequest( IS_PARTNER_READY, "POST", sServerURL, actionString ); delete [] actionString; mQueuedRequests.push_back( q ); } else if( mGameID != NULL && mGameReady && curTime - mTimeLastReportedAlive > mTimeBetweenReports ) { // set new time here (even though response not received yet) // to avoid sending multiple reports before first response seen. mTimeLastReportedAlive = curTime; char *actionString = autoSprintf( "action=report_alive" "&game_id=%s" "&game_passcode=%s" "&player_number=%s", mGameID, mGamePasscode, mPlayerNumber ); QueuedRequest *q = new QueuedRequest( REPORT_ALIVE, "POST", sServerURL, actionString ); delete [] actionString; mQueuedRequests.push_back( q ); } // now process requests that have already been created if( mCurrentRequest != NULL ) { int stepResult = mCurrentRequest->step(); if( stepResult == -1 ) { // error setError( "ERROR: Failed to get a response from server." ); delete mCurrentRequest; mCurrentRequest = NULL; mCurrentType = NONE; return step(); } else if( stepResult == 0 ) { // still waiting return true; } else if( stepResult == 1 ) { // done char *result = mCurrentRequest->getResult(); //printf( "Result from server: %s\n", result ); SimpleVector *tokens = tokenizeString( result ); char resultWellFormatted = true; if( strstr( result, "ERROR:" ) != NULL ) { setError( result ); } else if( mCurrentType == GET_SERVER_URL ) { if( tokens->size() == 1 ) { char *returnedURL = *( tokens->getElement( 0 ) ); if( sServerURL != NULL ) { delete [] sServerURL; } sServerURL = stringDuplicate( returnedURL ); // we have a server URL // send a request for a player ID, if needed if( mPlayerID == NULL ) { // request an ID QueuedRequest *q = new QueuedRequest( GET_ID, "POST", sServerURL, "action=get_player_id" ); mQueuedRequests.push_back( q ); } } else { resultWellFormatted = false; } } else if( mCurrentType == GET_ID ) { if( tokens->size() == 1 ) { char *returnedID = *( tokens->getElement( 0 ) ); mPlayerID = stringDuplicate( returnedID ); SettingsManager::setSetting( "playerID", mPlayerID ); } else { resultWellFormatted = false; } } else if( mCurrentType == CREATE ) { if( tokens->size() == 4 ) { mGameID = stringDuplicate( *( tokens->getElement( 0 ) ) ); mGamePasscode = stringDuplicate( *( tokens->getElement( 1 ) ) ); mPlayerNumber = stringDuplicate( *( tokens->getElement( 2 ) ) ); setBlockTransformFromString( *( tokens->getElement( 3 ) ) ); // wait before checking mTimeLastCheckedReady = time( NULL ); } else { resultWellFormatted = false; } } else if( mCurrentType == JOIN_FRIEND || mCurrentType == JOIN_STRANGER ) { if( tokens->size() == 4 ) { mGameID = stringDuplicate( *( tokens->getElement( 0 ) ) ); mGamePasscode = stringDuplicate( *( tokens->getElement( 1 ) ) ); mPlayerNumber = stringDuplicate( *( tokens->getElement( 2 ) ) ); setBlockTransformFromString( *( tokens->getElement( 3 ) ) ); if( mCurrentType == JOIN_FRIEND ) { // ready now mGameReady = true; } else { // still need to check for ready mTimeLastCheckedReady = time( NULL ); } } else { resultWellFormatted = false; } } else if( mCurrentType == IS_PARTNER_READY ) { if( tokens->size() == 1 ) { char *readyFlag = *( tokens->getElement( 0 ) ); if( readyFlag[0] == '1' ) { mGameReady = true; } mTimeLastCheckedReady = time( NULL ); } else { resultWellFormatted = false; } } else if( mCurrentType == REPORT_ALIVE ) { if( tokens->size() == 1 ) { char *successFlag = *( tokens->getElement( 0 ) ); if( successFlag[0] != '1' ) { setError( "ERROR: Reporting alive status failed." ); } else { // server know's we're alive mTimeLastReportedAlive = time( NULL ); } } else { resultWellFormatted = false; } } else if( mCurrentType == POST_MOVE ) { if( tokens->size() == 1 ) { char *successFlag = *( tokens->getElement( 0 ) ); if( successFlag[0] != '1' ) { setError( "ERROR: Posting move failed." ); } else { // server know's we're alive mTimeLastReportedAlive = time( NULL ); } } else { resultWellFormatted = false; } } else if( mCurrentType == GET_CHANGES ) { resultWellFormatted = false; if( tokens->size() > 2 ) { int numRead = sscanf( *( tokens->getElement( 0 ) ), "%lu", &mSecondsSincePartnerActed ); if( numRead == 1 ) { delete [] mLastStateSeen; mLastStateSeen = stringDuplicate( *( tokens->getElement( 1 ) ) ); int numChangedColumns; int numRead = sscanf( *( tokens->getElement( 2 ) ), "%d", &numChangedColumns ); if( numRead == 1 ) { if( tokens->size() >= 3 + numChangedColumns ) { resultWellFormatted = true; // server know's we're alive mTimeLastReportedAlive = time( NULL ); SimpleVector dirtyColumns; int i; for( i=0; igetElement( i + 3 ) ); if( strcmp( mPlayerNumber, "2" ) == 0 ) { // player 2 uses opposite colors on // server flipColorCodes( columnString ); } char *transformedString = transformColumnString( columnString ); dirtyColumns.push_back( transformedString ); } mGridToUpdate->setColumns( &dirtyColumns ); mGridToUpdate->clearDirtyFlags(); for( i=0; isize(); i++ ) { delete [] *( tokens->getElement( i ) ); } delete tokens; delete [] result; // clear current request for next step delete mCurrentRequest; mCurrentRequest = NULL; mCurrentType = NONE; return step(); } } else { if( mQueuedRequests.size() > 0 ) { QueuedRequest *q = *( mQueuedRequests.getElement( 0 ) ); mQueuedRequests.deleteElement( 0 ); mCurrentType = q->mType; mCurrentRequest = new WebRequest( q->mMethod, q->mURL, q->mBody ); delete q; return step(); } } // done with all work return false; } char Client::isClientReady() { // do we have a server URL yet? if( sServerURL != NULL ) { // do we have an ID yet? if( mPlayerID != NULL ) { return true; } } return false; } void Client::createGame() { char *actionString = autoSprintf( "action=create_for_friend&" "player_id=%s", mPlayerID ); QueuedRequest *q = new QueuedRequest( CREATE, "POST", sServerURL, actionString ); delete [] actionString; mQueuedRequests.push_back( q ); step(); } void Client::joinGame( char *inGameID ) { char *actionString; RequestType t; if( inGameID != NULL ) { actionString = autoSprintf( "action=join_with_friend&" "player_id=%s&game_id=%s", mPlayerID, inGameID ); t = JOIN_FRIEND; } else { actionString = autoSprintf( "action=join_with_stranger&" "player_id=%s", mPlayerID ); t = JOIN_STRANGER; } QueuedRequest *q = new QueuedRequest( t, "POST", sServerURL, actionString ); delete [] actionString; mQueuedRequests.push_back( q ); step(); } char Client::postMove( BlockGrid *inGrid ) { char returnVal = false; SimpleVector *dirtyColumns = inGrid->getDirtyColumns(); // do nothing if there are no dirty columns to send int numDirty = dirtyColumns->size(); if( numDirty > 0 ) { char *actionString = autoSprintf( "action=post_move&game_id=%s" "&game_passcode=%s&player_number=%s" "&num_dirty_columns=%d", mGameID, mGamePasscode, mPlayerNumber, numDirty ); for( int i=0; igetElement( i ) ); if( strcmp( mPlayerNumber, "2" ) == 0 ) { // player 2 uses opposite colors on server flipColorCodes( columnString ); } char *transformedString = transformColumnString( columnString ); delete [] columnString; columnString = transformedString; // add to actionString char *newActionString = autoSprintf( "%s&dirty_column_%d=%s", actionString, i, columnString ); delete [] actionString; actionString = newActionString; delete [] columnString; } QueuedRequest *q = new QueuedRequest( POST_MOVE, "POST", sServerURL, actionString ); delete [] actionString; mQueuedRequests.push_back( q ); step(); returnVal = true; } delete dirtyColumns; return returnVal; } void Client::getChanges( BlockGrid *inGrid ) { mGridToUpdate = inGrid; char *actionString = autoSprintf( "action=get_changed_columns&game_id=%s" "&game_passcode=%s&player_number=%s" "&last_state_seen=%s", mGameID, mGamePasscode, mPlayerNumber, mLastStateSeen ); QueuedRequest *q = new QueuedRequest( GET_CHANGES, "POST", sServerURL, actionString ); delete [] actionString; mQueuedRequests.push_back( q ); step(); } char *Client::getGameID() { return mGameID; } unsigned long Client::getSecondsSincePartnerActed() { return mSecondsSincePartnerActed; } char Client::isGameReady() { return mGameReady; } int Client::getSharedWorldIndex( int mNumWorlds ) { if( !mGameReady ) { return 0; } else { // add all chars in ID together and mod them int numChars = strlen( mGameID ); int sum = 0; for( int i=0; i=0 && index < 16 ) { mBlockTransform[i] = index; } } delete [] parts[i]; } delete [] parts; } char *Client::transformColumnString( char *inColumnString ) { // first part is column number... skip it int numParts; char **parts = split( inColumnString, "_", &numParts ); int i; for( i=1; i Image *readTGA( const char *inFileName ) { return readTGA( "graphics", inFileName ); } Image *readTGA( const char *inFolderName, const char *inFileName ) { File tgaFile( new Path( inFolderName ), inFileName ); FileInputStream tgaStream( &tgaFile ); TGAImageConverter converter; return converter.deformatImage( &tgaStream ); } double smoothBlend( double inValue ) { return 1 - ( sin( inValue * M_PI + M_PI / 2 ) + 1 ) / 2; } between-6+dfsg1.orig/game7/gameSource/tile.png0000640000175000017500000000222111102361020017755 0ustar pabspabs‰PNG  IHDR@)…î~PLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*LIDATHÇÅU;Â0 5„„L,e`±É{˜dîÂHHˆ…!48©Ó:i/X%jý>~™Á ²êdòÎÊû€©ë¬ó‹7€> €ð°mPÿvk즪ôçoM™5ÿú©0ì£&Qûí þT-‚OÃû¨IL|¾>d`‡cÖ4Yr…”…ñÄ—û³GÝzyk½1J-„å îÖKß{0\MUéy-UÀ¦½ŽáCÒ‚Qò¥O"…xÕÒˆvø-û튛Ê# 6†ï¡ Éñ(ì€s¹è®ï'á[±ÄØáÞ j¸‰» ÀÓ)J*· “°.-126þ» À¥HeëX6.…+Ñ‹'â¸ì:i­Eߟ`úÔˆ8>_|ƒ•Fšjè"£ÂkÁþÍLh•ôܽ³RóÑ¿”?ÌB”È{"ÈE¾gZÃñäÉÃëÒÓ:Õ¾xýIEND®B`‚between-6+dfsg1.orig/game7/gameSource/nightTile.png0000640000175000017500000000156511102165400020765 0ustar pabspabs‰PNG  IHDR‘h6PLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*0IDAT(Ïc¼}û6å€4S¶mÛF‚êI“&‘ :77—Õžžž$¨VQQeÃ!o ‹º$˜¸IEND®B`‚between-6+dfsg1.orig/game7/gameSource/blockBuilder.png0000640000175000017500000000237611065537566021470 0ustar pabspabs‰PNG  IHDR@@% æ‰PLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*¹IDAThÞíZÑÃ0u¢ŒbãÛ¥ ãì†ÁÃÜR.êTãäöðG•ª.øñ0ª.ñ8Â;¯5¼ùrÀ8ð‰ îãÀív»W†/`‡S­¤ ¥(°5î#ª!„“6¢šsnÔò²™;ccJ ‰2?ó+ïágÈŽ,²Æ.ÎÊ£ÜJ!Ø!„€ˆ|zÄX+lpœØèôü-D¼Zã·ˆ1%~À1 Ü ”ò“¦ìõš¸/CõgtN;ló´ ˆ2cÀrÜp-}í¨BíŽVQ}0¸ÄRGÓ YJQ´kßjþ§Û5’ZÉFÈDÁZE±1²ñ)$MÍ;ë*‘à ªÒìì,£’ðÏÈ@£÷0ÀäÎv‰eeÔ½ÝÑÚaÝ …´”Ø€©–É„ÌFŒUtÀ¬•ò<]+Áá_…xÔªÌ\:`¦eï=hU¡ßsð$3Ít)$õ"H!›VBq"³”•vÚ¦.Ù@cÀÈ˦w½¦k%̺Q-Ì~–Sêͯ8LxúpÃ;~&6ë…QÔ.þ!à€pÀ8àþ-€o ŠÃÅhIEND®B`‚between-6+dfsg1.orig/game7/gameSource/Sprite.cpp0000640000175000017500000001426311377036601020317 0ustar pabspabs#include "Sprite.h" #include "common.h" #include "minorGems/math/geometry/Angle3D.h" Sprite::Sprite( const char *inImageFileName, char inTransparentLowerLeftCorner, int inNumFrames, int inNumPages ) { Image *spriteImage = readTGA( inImageFileName ); if( spriteImage == NULL ) { printf( "Failed to read image file: %s\n", inImageFileName ); } initTexture( spriteImage, inTransparentLowerLeftCorner, inNumFrames, inNumPages ); delete spriteImage; } Sprite::Sprite( Image *inImage, char inTransparentLowerLeftCorner, int inNumFrames, int inNumPages ) { initTexture( inImage, inTransparentLowerLeftCorner, inNumFrames, inNumPages ); } void Sprite::initTexture( Image *inImage, char inTransparentLowerLeftCorner, int inNumFrames, int inNumPages ) { mNumFrames = inNumFrames; mNumPages = inNumPages; Image *spriteImage = inImage; Image *imageToDelete = NULL; if( spriteImage->getNumChannels() == 3 && inTransparentLowerLeftCorner ) { // use lower-left corner color as transparent color for alpha Image *fourChannelImage = new Image( spriteImage->getWidth(), spriteImage->getHeight(), 4, false ); // copy first three for( int c=0; c<3; c++ ) { fourChannelImage->pasteChannel( spriteImage->getChannel( c ), c ); } double *r = fourChannelImage->getChannel( 0 ); double *g = fourChannelImage->getChannel( 1 ); double *b = fourChannelImage->getChannel( 2 ); // index of transparency int tI = fourChannelImage->getWidth() * ( fourChannelImage->getHeight() - 1 ); // color of transparency double tR = r[tI]; double tG = g[tI]; double tB = b[tI]; double *alpha = fourChannelImage->getChannel( 3 ); int numPixels = fourChannelImage->getWidth() * fourChannelImage->getHeight(); for( int i=0; igetWidth() / mNumPages; mBaseScaleY = spriteImage->getHeight() / mNumFrames; if( imageToDelete != NULL ) { delete imageToDelete; } mFlipHorizontal = false; mHorizontalOffset = 0; mCurrentPage = 0; } Sprite::~Sprite() { delete mTexture; } // opt (found with profiler) // only construct these once, not every draw call Vector3D corners[4]; void Sprite::draw( int inFrame, double inRotation, Vector3D *inPosition, double inScale, double inFadeFactor, Color *inColor ) { /* printf( "Drawing sprite %d, r%f, (%f,%f), s%f, f%f\n", (int)(this), inRotation, inPosition->mX, inPosition->mY, inScale, inFadeFactor ); */ // profiler opt: // this is expensive, and the game never needs it // (all frame references are specific and never auto-cycling) // inFrame = inFrame % mNumFrames; double xRadius = inScale * mBaseScaleX / 2; double yRadius = inScale * mBaseScaleY / 2; double xOffset = mHorizontalOffset * inScale; if( mFlipHorizontal ) { xRadius = -xRadius; } // first, set up corners relative to 0,0 // loop is unrolled here, with all offsets added in // also, mZ ignored now, since rotation no longer done double posX = inPosition->mX + xOffset; double posY = inPosition->mY; corners[0].mX = posX - xRadius; corners[0].mY = posY - yRadius; //corners[0].mZ = 0; corners[1].mX = posX + xRadius; corners[1].mY = posY - yRadius; //corners[1].mZ = 0; corners[2].mX = posX + xRadius; corners[2].mY = posY + yRadius; //corners[2].mZ = 0; corners[3].mX = posX - xRadius; corners[3].mY = posY + yRadius; //corners[3].mZ = 0; // int i; // now rotate around center // then add inPosition so that center is at inPosition // Found with profiler: ignore rotation, since game doesn't use it anyway. // Angle3D rot( 0, 0, inRotation ); // found with profiler: // unroll this loop /* for( i=0; i<4; i++ ) { corners[i].mX += xOffset; // corners[i].rotate( &rot ); corners[i].add( inPosition ); } */ if( inColor != NULL ) { glColor4f( inColor->r, inColor->g, inColor->b, inFadeFactor ); } else { glColor4f( 1, 1, 1, inFadeFactor ); } mTexture->enable(); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); double textXA = (1.0 / mNumPages) * mCurrentPage; double textXB = textXA + (1.0 / mNumPages ); double textYB = (1.0 / mNumFrames) * inFrame; double textYA = textYB + (1.0 / mNumFrames ); glBegin( GL_QUADS ); { glTexCoord2f( textXA, textYA ); glVertex2d( corners[0].mX, corners[0].mY ); glTexCoord2f( textXB, textYA ); glVertex2d( corners[1].mX, corners[1].mY ); glTexCoord2f( textXB, textYB ); glVertex2d( corners[2].mX, corners[2].mY ); glTexCoord2f( textXA, textYB ); glVertex2d( corners[3].mX, corners[3].mY ); } glEnd(); mTexture->disable(); } between-6+dfsg1.orig/game7/gameSource/BlockGrid.h0000640000175000017500000000452311077456713020363 0ustar pabspabs#ifndef BLOCK_GRID_INCLUDED #define BLOCK_GRID_INCLUDED #include "minorGems/util/SimpleVector.h" #include "Block.h" #include "World.h" class BlockGrid { public: // sets world to NULL // setWorld must be called before using the resulting class BlockGrid(); // the world that this grid is in BlockGrid( World *inWorld ); ~BlockGrid(); void setWorld( World *inWorld ); void setDepthLayer( int inDepthLayer ); // blocks destroyed when corresponding world destroyed // return true if add succeeded char add( Block *inBlock, int inX, int inY ); // gets all blocks managed by this grid SimpleVector *getAllBlocks(); // can return NULL Block *getBlock( int inX, int inY ); Block *removeBlock( int inX, int inY ); // is the column at world position inX full? char isColumnFull( int inX ); // for synching with server // gets all dirty columns as strings in format that matches // server's protocol.txt specification // vector and strings destroyed by caller SimpleVector *getDirtyColumns(); void clearDirtyFlags(); // sets columns using server formatted column strings void setColumns( SimpleVector *inColumns ); protected: World *mWorld; // depth layer to set for all blocks added to this grid int mDepthLayer; static const int mBlockColumns = 40; static const int mBlockRows = 9; Block *mBlocks[mBlockRows][mBlockColumns]; char mDirtyFlags[mBlockColumns]; void initBlocks(); // coordinate conversion functions int worldToGridC( int inX ) { return inX + mBlockColumns / 2; } int worldToGridR( int inY ) { return inY - 1; } int gridToWorldX( int inC ) { return inC - mBlockColumns / 2; } int gridToWorldY( int inR ) { return inR + 1; } }; #endif between-6+dfsg1.orig/game7/gameSource/TargetBlock.cpp0000640000175000017500000000326011377036601021245 0ustar pabspabs#include "TargetBlock.h" #include "minorGems/util/random/StdRandomSource.h" extern StdRandomSource randSource; void TargetBlock::initShimmerState( int inShimmerTime ) { mState = 0; if( inShimmerTime != -1 ) { mShimmerTime = inShimmerTime; } else { mShimmerTime = randSource.getRandomBoundedInt( 0, 1000 ); } } TargetBlock::TargetBlock( Image *inOverlayImage, const char *inColorSignature, int inShimmerTime ) : Block( inOverlayImage, inColorSignature ) { initShimmerState( inShimmerTime ); // replace sprite with plain overlay delete mSprite; mSprite = new Sprite( mOverlayImage, false ); } TargetBlock::TargetBlock( Sprite *inSprite, const char *inColorSignature, int inShimmerTime ) : Block( inSprite, inColorSignature ) { initShimmerState( inShimmerTime ); } void TargetBlock::setState( int inState ) { mState = inState; } TargetBlock *TargetBlock::copy() { return new TargetBlock( mOverlayImage, mColorSignature, mShimmerTime ); } void TargetBlock::step() { mShimmerTime ++; switch( mState ) { case 0: mFadeFactor = 0.3 + 0.2 * sin( mShimmerTime / 25.0 ); break; case 1: // faster mFadeFactor = 0.3 + 0.2 * sin( mShimmerTime / 5.0 ); break; case 2: // invisible // but fade out gradually mFadeFactor -= 0.04; if( mFadeFactor < 0 ) { mFadeFactor = 0; } break; } } between-6+dfsg1.orig/game7/gameSource/language.txt0000640000175000017500000000001011070251511020637 0ustar pabspabsEnglish between-6+dfsg1.orig/game7/gameSource/music/0000750000175000017500000000000011435543354017461 5ustar pabspabsbetween-6+dfsg1.orig/game7/gameSource/music/music.tga0000640000175000017500000006222211103622362021270 0ustar pabspabs@†ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ’’’Û’’’Û’’’Û’’’Û’’’ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’’Û’’’Û’’’Û’’ÿÿÿÿÿÿÛ’’’Û’’’Û’’’Û’ÿÿÿÿÿÿ’Û’’’Û’’’Û’’’ÿÿÿÿÿÿÿÿÿÿÿÿ’’Û’’’ÿÿÿÿÿÿÿÿ’’’Û’’’Û’’’Û’’’Û’’’Ûÿÿÿÿÿÿÿÿ’’ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÿÿÿÿÿÿÿÿÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ’’’Û’’’Û’’’ÿÿÿÿÿÿÿÿ’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛ’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’ÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’ÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÛ’’’Û’’’ÿÀÛÿÀÛÿÀÛÿÀÛÿÀÛÿÀÛÿÀÛÿÀÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ’’’Û’’ÀÿÀÿ’ÀÿÀÿÛ’’’ÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÛ’’ÀÿÀÿ’ÀÿÀÿÛÀÿÀÿ’Àÿÿÿ’’ÿÀÿÀÿÀÿÀ’’Û’’’ÛÀÿÀÿ’ÀÿÀÿ’’Û’’’Û’ÿÀÿÀÿÀÿÀÛ’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’ÛÀÿÀÿ’ÀÿÀÿ’ÀÿÀÿ’ÀÿÀÿÛÀÿÀÿ’ÀÿÀÿ’ÀÿÀÿ’ÀÿÀÿÛ’’’Û’’’Û’’’Û’’’ÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’ÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÛ’’’Û’’’Û’’’Û’’’Û’ÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÛ’’’Û’’’ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’ÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÛ’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’ÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’ÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÛ’’’Û’’’ÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÛ’’’Û’’’ÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÛ’’’Û’’’ÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÛ’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’ÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ’’’Û’’’Û’’’Û’ÿÿÿÿÿÿ’Û’’’Û’’’Û’ÿÿÿÿÿÿ’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’ÿÿÿÿÿÿ’Û’’’Ûÿÿÿÿ’’ÿÿÿÿ’Û’ÿÿÿÿÿÿ’Û’’’Ûÿÿÿÿ’’ÿÿÿÿ’Û’’’Û’’’ÛÿÿÿÿÛÛÿÿÿÿÛÛ’’’Ûÿÿÿÿ’ÿÿÿÿÛÛÿÿÿÿÛÛÛÛÛÛÿÿÿÿÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÿÿÿÿÛÛÛÛÛÛÿÿÿÿÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ’’’Ûÿÿÿÿ’ÿÿÿÿÛ’’’ÿÿÿÿ’’’ÿÿÿÿÛÿÿÿÿ’ÿÿÿÿÛ’’’ÿÿÿÿ’’’ÿÿÿÿÛ’’’Û’’’Û’’’Û’’’Û’’’Û’’’ÿÿÿÿ’’’ÿÿÿÿÛ’’’Û’’’ÿÿÿÿ’’’ÿÿÿÿÛ’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’ÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ’ÀÿÀÿÀÿ’ÀÿÀÿÀÿÀÿ’’Û’’ÀÿÀÿ’ÀÿÀÿÀÿÀÿ’’ÀÿÀÿÀÿÀÿ’’Û’’’ÀÿÀÿÀÿÀÿÀÿÀÿ’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’ÀÿÀÿÀÿÀÿÛ’’ÀÿÀÿÀÿÀÿÛ’’’Û’’ÀÿÀÿÀÿÀÿÛ’’’Û’ÀÿÀÿÀÿÀÿ’Û’’ÀÿÀÿÀÿÀÿÛ’ÀÿÀÿÀÿÀÿ’Û’’’Û’’’Û’’’Û’’’ÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’ÿÀÿÀÿÀÿÀÿÀÛ’’’Û’’’Û’’’Û’’’ÿÀÿÀÿÀÿÀ’’ÛÛÛÛÛÛÛÛÛÛÛÛÿÀÛÿÀÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ’’’Û’ÿÀÿÀÿÀÿÀ’Û’’’Û’ÿÀÿÀÿÀÿÀ’Û’’’Û’’’ÿÀÿÀÿÀÿÀ’’Û’’’Û’’’Û’’’Û’’’Û’’’ÿÀÿÀÿÀÿÀÿÀÿÀ’ÿÀÿÀÿÀÿÀ’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’ÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’ÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿ’Û’’’Û’’’ÀÿÀÿÀÿÀÿÀÿÀÿ’’Û’’’Û’’’ÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿ’Û’ÀÿÀÿ’’Û’’’ÀÿÀÿÀÿÀÿÀÿÀÿÀÿÀÿÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÀÿÀÿÀÿÀÿÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ’ÀÿÀÿÀÿÀÿ’Û’’’Û’’ÀÿÀÿÀÿÀÿÛ’’’Û’’ÀÿÀÿÀÿÀÿÛ’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’ÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Ûÿÿÿÿ’ÿÿÿÿ’ÿÿÿÿ’ÿÿÿÿÛ’’’Ûÿÿÿÿ’ÿÿÿÿ’ÿÿÿÿ’ÿÿÿÿÛÿÿÿÿ’ÿÿÿÿ’ÿÿÿÿ’ÿÿÿÿÛ’’’Ûÿÿÿÿ’ÿÿÿÿ’ÿÿÿÿ’ÿÿÿÿÛ’’’Û’’’ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛ’’’ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛÛÿÿÿÿÛÛÿÿÿÿÛÛÿÿÿÿÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÿÿÿÿÛÛÿÿÿÿÛÛÿÿÿÿÛÛÿÿÿÿÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’Û’’’between-6+dfsg1.orig/game7/gameSource/blockNoise.png0000640000175000017500000000532311103220411021115 0ustar pabspabs‰PNG  IHDR@œ`ÁPLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*ŽIDATHÇ=WÙrÛÆ ƒÁFEK¢Rr9þ¬üyW*&)n ±³ß‡ö5ŸXTÐÝgka­õ²,˲ „.—‹sn³Ùl6ÆBÈÓ4 ¼½½…aÈ”RMÓô}Ÿçùn·sÎB0ÆÞ{k­Öºïû¢(¢(RJc˜1&‚Ýn'„À×u= C†Œ±®ë(¥EQXk???‡a ”2cL–e!„¥´,ËÕjE!„pÎÇ#!ÄZ[…R*MS,¥”RžN§,Ë u­õãñBpΕRã8 !„çóyÜ÷}Û¶Bˆ4M9çc­õétz<yžEAéû¾,KŒ±1†(¥ú¾_–Ekíœ3ÆPJ«ªZ¯×ÖÚóù¬”jÛÖCB`)å²,RÊëõºÛí´Öyž3ÆŒ1Î9çB¨®ë¢(´ÖBæœ[–¥ic BÈ{oŒaŒAàœSJaŒ…Apν÷„sE‘sîåå%Š¢ †aǪO§“1& Cï=Bhš&¬µF àµÆ7M“çùý~ßn·Y–cŒ1ÿþûoY–UUi­ÉívëûÞZË»^¯QQJƒ ¸\.˲„a˜!¬µ·Û ÿý÷ßι××× >??»® ‚àõõxQ–%¥tš&@Í9‡çyöÞ‡ah­½÷ιq¥”ÏÏÏ„ßkÀà É<Ïó<3Æ’$aŒÕuM)çY)u»Ý>>>†a€¹ñÏŸ?—e™¦‰sþõë×0 µÖBÛ¶išzïÿùçïý·oßV«aŒ øÝnßÞÞB}ß?­u×uaGÆØ×¯_1Æÿý÷ßåraišn6†Â{<°¨eYæyÞl6ÖZ„P–eß¿¯ëú~¿c­µ”RkÍsÎGJéóó3c `Y­V˲ADfƘ¾ïo·!d½^K)ámQYkÓ4 ‚@)u¹\ʲÔZã¶mA–ó<ßï÷§§'Îy’$°¥ÃáðåË)%¬A)E~üøq:0Æã$I!¿ÑÀ3ÆcBˆiš@R¸ï{„üM)u>Ÿ“$Áçyî½?»Ý. C)% I(¥„ëõê½ã¸ªªûý>Ïó0 Œ±··· ~W !t¹Z­”Rι(ŠÀ€œóq÷û}EÞû_ýãx80Æq¿¿¿o60è¶iBH’$·ÛÍ{ÏÂ0]×%I›¡”‚`Ú¶=NZk<Ï3çÜZÛ¶-8—µ–RúóçO°C!´D¡”²išüÿ?ðhåååzSJÝï÷ªª¬µ}ß3è„Ë#„E1M“Öz½^#„cY–u]×÷}ØZk­ýå9ƒÏ"„öû=!d·ÛqÎÏçsUUð8 ¥¯0(DhÛ¶¶¯¯¯w„„û‡€˜Å<Ï [xX(„-ËÑQ⽂Ò6Š¢,Ë´Ö‡Ã!I’¢(8çô¯¿þ‚­‡Óé»âœ™!{â8‚ m[m!„ jã8ޢĀ1ÇÑZKæõ}¯”Â`Ú]׸‹¢0Æ`Œ­µ ip¤ãñ˜¦éz½& ²¦iªªºÝnà™·ÛíxmDepthLayer; } else if( mB != NULL ) { mDepthLayer = mB->mDepthLayer; } else { // dummy mDepthLayer = 0; mDummy = true; } } double BlendedBlock::getFractionDone() { return (double)mStepsDone / (double)mStepsTotal; } void BlendedBlock::draw( double inRotation, Vector3D *inPosition, double inScale, double inFadeFactor, Color *inColor ) { if( mDummy ) { return; } double blendB = (double)mStepsDone / (double)mStepsTotal; blendB = smoothBlend( blendB ); double blendA = 1.0 - blendB; if( mA != NULL ) { mA->draw( inRotation, inPosition, inScale, blendA * inFadeFactor, inColor ); } if( mB != NULL ) { mB->draw( inRotation, inPosition, inScale, blendB * inFadeFactor, inColor ); } } void BlendedBlock::step() { mStepsDone ++; if( mStepsDone > mStepsTotal ) { mStepsDone = mStepsTotal; } if( mDummy ) { return; } double blendB = (double)mStepsDone / (double)mStepsTotal; blendB = smoothBlend( blendB ); double blendA = 1.0 - blendB; mX = 0; mY = 0; mScale = 1.0; if( mA != NULL && mB == NULL ) { mX = mA->mX; mY = mA->mY; mScale = mA->mScale; } else if( mA == NULL && mB != NULL ) { mX = mB->mX; mY = mB->mY; mScale = mB->mScale; } else if( mA != NULL && mB != NULL ) { mX = blendA * mA->mX + blendB * mB->mX; mY = blendA * mA->mY + blendB * mB->mY; mScale = blendA * mA->mScale + blendB * mB->mScale; } } between-6+dfsg1.orig/game7/gameSource/Star.h0000640000175000017500000000121311102345045017405 0ustar pabspabs#ifndef STAR_OBJECT_INCLUDED #define STAR_OBJECT_INCLUDED #include "GameObject.h" class Star : public GameObject { public: Star(); // shifts between position and fade of start and end stars void shiftBetween( Star *inA, Star *inB, int inNumSteps ); // override step function virtual void step(); double mBaseFade; protected: int mShimmerTime; double mShimmerRate; Star *mShiftA; Star *mShiftB; int mNumShiftSteps; int mNumShiftStepsDone; }; #endif between-6+dfsg1.orig/game7/gameSource/selector.png0000640000175000017500000000202111103106555020651 0ustar pabspabs‰PNG  IHDR €åüMPLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*ÌIDAThÞí™Ë€ Yãÿÿòz3¢´ŸŽF˜ÊÖQ¹\;¦à÷€¹}ÙuqI÷ɭiªo핲öó|d̽G‹œ÷aTQ|ˆ,  °5p ŽáÊœêhu¾N&ì®m™l2ÏòI>¥V/’c”lÞœSŒGÂ?ÀÈ"ø~€¦øRšâT~~€¼Ô´{ŽVw<µÕ—Æðê¹MöZìJœ€Ûü?À8øø~€àß,º‹á³‰«IEND®B`‚between-6+dfsg1.orig/game7/gameSource/Envelope.cpp0000640000175000017500000000545711103404573020625 0ustar pabspabs#include "Envelope.h" #include // #include Envelope::Envelope( double inAttackTime, double inDecayTime, double inSustainLevel, double inReleaseTime, int inMaxNoteLengthInGridSteps, int inGridStepDurationInSamples ) : mNumComputedEnvelopes( inMaxNoteLengthInGridSteps ), mEvelopeLengths( new int[ inMaxNoteLengthInGridSteps ] ), mComputedEnvelopes( new double*[ inMaxNoteLengthInGridSteps ] ) { for( int i=0; i 0 ); mComputedEnvelopes[i][s] = t / inAttackTime; } else if( t < inAttackTime + inDecayTime ) { // assert( inDecayTime > 0 ); // decay down to sustain level mComputedEnvelopes[i][s] = ( 1.0 - inSustainLevel ) * ( inAttackTime + inDecayTime - t ) / ( inDecayTime ) + inSustainLevel; } else if( 1.0 - t > inReleaseTime ) { mComputedEnvelopes[i][s] = inSustainLevel; } else { if( inReleaseTime > 0 ) { mComputedEnvelopes[i][s] = inSustainLevel - inSustainLevel * ( inReleaseTime - ( 1.0 - t ) ) / inReleaseTime; } else { // release time 0 // hold sustain until end mComputedEnvelopes[i][s] = inSustainLevel; } } } // test code to output evelopes for plotting in gnuplot if( false && i == 0 ) { FILE *file = fopen( "env0.txt", "w" ); for( int s=0; s mNumShiftSteps ) { // stop shifting mShiftA = NULL; mShiftB = NULL; } else { double bBlend = mNumShiftStepsDone / (double)mNumShiftSteps; bBlend = smoothBlend( bBlend ); double aBlend = 1 - bBlend; mX = mShiftA->mX * aBlend + mShiftB->mX * bBlend; mY = mShiftA->mY * aBlend + mShiftB->mY * bBlend; mFadeFactor = mShiftA->mFadeFactor * aBlend + mShiftB->mFadeFactor * bBlend; } } } between-6+dfsg1.orig/game7/gameSource/mac/0000750000175000017500000000000011435543354017101 5ustar pabspabsbetween-6+dfsg1.orig/game7/gameSource/mac/SDLMain.h0000640000175000017500000000046311104001330020455 0ustar pabspabs/* SDLMain.m - main entry point for our Cocoa-ized SDL app Initial Version: Darrell Walisser Non-NIB-Code & other changes: Max Horn Feel free to customize this file to suit your needs */ #import @interface SDLMain : NSObject @end between-6+dfsg1.orig/game7/gameSource/mac/SDLMain.m0000640000175000017500000002572411104001330020471 0ustar pabspabs/* SDLMain.m - main entry point for our Cocoa-ized SDL app Initial Version: Darrell Walisser Non-NIB-Code & other changes: Max Horn Feel free to customize this file to suit your needs */ #import #import "SDLMain.h" #import /* for MAXPATHLEN */ #import /* For some reaon, Apple removed setAppleMenu from the headers in 10.4, but the method still is there and works. To avoid warnings, we declare it ourselves here. */ @interface NSApplication(SDL_Missing_Methods) - (void)setAppleMenu:(NSMenu *)menu; @end /* Use this flag to determine whether we use SDLMain.nib or not */ #define SDL_USE_NIB_FILE 0 /* Use this flag to determine whether we use CPS (docking) or not */ #define SDL_USE_CPS 1 #ifdef SDL_USE_CPS /* Portions of CPS.h */ typedef struct CPSProcessSerNum { UInt32 lo; UInt32 hi; } CPSProcessSerNum; extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); #endif /* SDL_USE_CPS */ static int gArgc; static char **gArgv; static BOOL gFinderLaunch; static BOOL gCalledAppMainline = FALSE; static NSString *getApplicationName(void) { NSDictionary *dict; NSString *appName = 0; /* Determine the application name */ dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); if (dict) appName = [dict objectForKey: @"CFBundleName"]; if (![appName length]) appName = [[NSProcessInfo processInfo] processName]; return appName; } #if SDL_USE_NIB_FILE /* A helper category for NSString */ @interface NSString (ReplaceSubString) - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; @end #endif @interface SDLApplication : NSApplication @end @implementation SDLApplication /* Invoked from the Quit menu item */ - (void)terminate:(id)sender { /* Post a SDL_QUIT event */ SDL_Event event; event.type = SDL_QUIT; SDL_PushEvent(&event); } @end /* The main class of the application, the application's delegate */ @implementation SDLMain /* Set the working directory to the .app's parent directory */ - (void) setupWorkingDirectory:(BOOL)shouldChdir { if (shouldChdir) { char parentdir[MAXPATHLEN]; CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); if (CFURLGetFileSystemRepresentation(url2, true, (UInt8 *)parentdir, MAXPATHLEN)) { assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */ } CFRelease(url); CFRelease(url2); } } #if SDL_USE_NIB_FILE /* Fix menu to contain the real app name instead of "SDL App" */ - (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName { NSRange aRange; NSEnumerator *enumerator; NSMenuItem *menuItem; aRange = [[aMenu title] rangeOfString:@"SDL App"]; if (aRange.length != 0) [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; enumerator = [[aMenu itemArray] objectEnumerator]; while ((menuItem = [enumerator nextObject])) { aRange = [[menuItem title] rangeOfString:@"SDL App"]; if (aRange.length != 0) [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; if ([menuItem hasSubmenu]) [self fixMenu:[menuItem submenu] withAppName:appName]; } [ aMenu sizeToFit ]; } #else static void setApplicationMenu(void) { /* warning: this code is very odd */ NSMenu *appleMenu; NSMenuItem *menuItem; NSString *title; NSString *appName; appName = getApplicationName(); appleMenu = [[NSMenu alloc] initWithTitle:@""]; /* Add menu items */ title = [@"About " stringByAppendingString:appName]; [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; [appleMenu addItem:[NSMenuItem separatorItem]]; title = [@"Hide " stringByAppendingString:appName]; [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; [appleMenu addItem:[NSMenuItem separatorItem]]; title = [@"Quit " stringByAppendingString:appName]; [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; /* Put menu into the menubar */ menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; [menuItem setSubmenu:appleMenu]; [[NSApp mainMenu] addItem:menuItem]; /* Tell the application object that this is now the application menu */ [NSApp setAppleMenu:appleMenu]; /* Finally give up our references to the objects */ [appleMenu release]; [menuItem release]; } /* Create a window menu */ static void setupWindowMenu(void) { NSMenu *windowMenu; NSMenuItem *windowMenuItem; NSMenuItem *menuItem; windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; /* "Minimize" item */ menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; [windowMenu addItem:menuItem]; [menuItem release]; /* Put menu into the menubar */ windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; [windowMenuItem setSubmenu:windowMenu]; [[NSApp mainMenu] addItem:windowMenuItem]; /* Tell the application object that this is now the window menu */ [NSApp setWindowsMenu:windowMenu]; /* Finally give up our references to the objects */ [windowMenu release]; [windowMenuItem release]; } /* Replacement for NSApplicationMain */ static void CustomApplicationMain (int argc, char **argv) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; SDLMain *sdlMain; /* Ensure the application object is initialised */ [SDLApplication sharedApplication]; #ifdef SDL_USE_CPS { CPSProcessSerNum PSN; /* Tell the dock about us */ if (!CPSGetCurrentProcess(&PSN)) if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) if (!CPSSetFrontProcess(&PSN)) [SDLApplication sharedApplication]; } #endif /* SDL_USE_CPS */ /* Set up the menubar */ [NSApp setMainMenu:[[NSMenu alloc] init]]; setApplicationMenu(); setupWindowMenu(); /* Create SDLMain and make it the app delegate */ sdlMain = [[SDLMain alloc] init]; [NSApp setDelegate:sdlMain]; /* Start the main event loop */ [NSApp run]; [sdlMain release]; [pool release]; } #endif /* * Catch document open requests...this lets us notice files when the app * was launched by double-clicking a document, or when a document was * dragged/dropped on the app's icon. You need to have a * CFBundleDocumentsType section in your Info.plist to get this message, * apparently. * * Files are added to gArgv, so to the app, they'll look like command line * arguments. Previously, apps launched from the finder had nothing but * an argv[0]. * * This message may be received multiple times to open several docs on launch. * * This message is ignored once the app's mainline has been called. */ - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename { const char *temparg; size_t arglen; char *arg; char **newargv; if (!gFinderLaunch) /* MacOS is passing command line args. */ return FALSE; if (gCalledAppMainline) /* app has started, ignore this document. */ return FALSE; temparg = [filename UTF8String]; arglen = SDL_strlen(temparg) + 1; arg = (char *) SDL_malloc(arglen); if (arg == NULL) return FALSE; newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); if (newargv == NULL) { SDL_free(arg); return FALSE; } gArgv = newargv; SDL_strlcpy(arg, temparg, arglen); gArgv[gArgc++] = arg; gArgv[gArgc] = NULL; return TRUE; } /* Called when the internal event loop has just started running */ - (void) applicationDidFinishLaunching: (NSNotification *) note { int status; /* Set the working directory to the .app's parent directory */ [self setupWorkingDirectory:gFinderLaunch]; #if SDL_USE_NIB_FILE /* Set the main menu to contain the real app name instead of "SDL App" */ [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; #endif /* Hand off to main application code */ gCalledAppMainline = TRUE; status = SDL_main (gArgc, gArgv); /* We're done, thank you for playing */ exit(status); } @end @implementation NSString (ReplaceSubString) - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString { unsigned int bufferSize; unsigned int selfLen = [self length]; unsigned int aStringLen = [aString length]; unichar *buffer; NSRange localRange; NSString *result; bufferSize = selfLen + aStringLen - aRange.length; buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar)); /* Get first part into buffer */ localRange.location = 0; localRange.length = aRange.location; [self getCharacters:buffer range:localRange]; /* Get middle part into buffer */ localRange.location = 0; localRange.length = aStringLen; [aString getCharacters:(buffer+aRange.location) range:localRange]; /* Get last part into buffer */ localRange.location = aRange.location + aRange.length; localRange.length = selfLen - localRange.location; [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; /* Build output string */ result = [NSString stringWithCharacters:buffer length:bufferSize]; NSDeallocateMemoryPages(buffer, bufferSize); return result; } @end #ifdef main # undef main #endif /* Main entry point to executable - should *not* be SDL_main! */ int main (int argc, char **argv) { /* Copy the arguments into a global variable */ /* This is passed if we are launched by double-clicking */ if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { gArgv = (char **) SDL_malloc(sizeof (char *) * 2); gArgv[0] = argv[0]; gArgv[1] = NULL; gArgc = 1; gFinderLaunch = YES; } else { int i; gArgc = argc; gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); for (i = 0; i <= argc; i++) gArgv[i] = argv[i]; gFinderLaunch = NO; } #if SDL_USE_NIB_FILE [SDLApplication poseAsClass:[NSApplication class]]; NSApplicationMain (argc, argv); #else CustomApplicationMain (argc, argv); #endif return 0; } between-6+dfsg1.orig/game7/gameSource/NightBackground.h0000640000175000017500000000117011102503757021555 0ustar pabspabs#ifndef NIGHT_BACKGROUND_INCLUDED #define NIGHT_BACKGROUND_INCLUDED #include "GameObject.h" // originally just for night background, but now more general class NightBackground : public GameObject { public: // direction -1 or +1 NightBackground( Color inColor, int inDirection ); virtual void draw( double inRotation, Vector3D *inPosition, double inScale, double inFadeFactor, Color *inColor ); private: Color mColor; int mDirection; }; #endif between-6+dfsg1.orig/game7/gameSource/Envelope.h0000640000175000017500000000230411103404573020256 0ustar pabspabs class Envelope { public: /** * Constructs an envelope. * * All parameters are in range 0..1, and sum of the three time * parameters must be <= 1. * * @param inMaxNoteLengthInGridSteps the maximum note length to * cover. Exact envelopes will be generated for notes up * to this length. * @param inGridStepDurationInSamples the number of samples * per grid step. */ Envelope( double inAttackTime, double inDecayTime, double inSustainLevel, double inReleaseTime, int inMaxNoteLengthInGridSteps, int inGridStepDurationInSamples ); ~Envelope(); /** * Gets an evenlope for a given note length. * * @return an evelope of values in [0,1] that can be indexed by * sample number. Will be destroyed when this class is destroyed. */ double *getEnvelope( int inNoteLengthInGridSteps ); private: int mNumComputedEnvelopes; int *mEvelopeLengths; double **mComputedEnvelopes; }; between-6+dfsg1.orig/game7/gameSource/GridTransition.cpp0000640000175000017500000000463711102126246022004 0ustar pabspabs#include "GridTransition.h" GridTransition::GridTransition( BlockGrid *inA, BlockGrid *inB, World *inWorld, int inNumTransitionSteps ) : mWorld( inWorld ), mFirstBlendedBlock( NULL ) { SimpleVector *blocksA = inA->getAllBlocks(); SimpleVector *blocksB = inB->getAllBlocks(); int indexA = 0; int indexB = 0; char doneA = false; char doneB = false; while( !( doneA && doneB ) ) { if( indexA == blocksA->size() ) { doneA = true; indexA = 0; } if( indexB == blocksB->size() ) { doneB = true; indexB = 0; } if( !( doneA && doneB ) ) { Block *blockA = NULL; Block *blockB = NULL; if( indexA < blocksA->size() ) { blockA = *( blocksA->getElement( indexA ) ); indexA ++; } if( indexB < blocksB->size() ) { blockB = *( blocksB->getElement( indexB ) ); indexB ++; } if( blockA != NULL || blockB != NULL ) { BlendedBlock * blockBlend = new BlendedBlock( blockA, blockB, inNumTransitionSteps ); if( mFirstBlendedBlock == NULL ) { mFirstBlendedBlock = blockBlend; } mWorld->add( blockBlend ); mBlocks.push_back( blockBlend ); } } } if( blocksA->size() == 0 && blocksB->size() == 0 ) { // empty to empty transition // one dummy block mFirstBlendedBlock = new BlendedBlock( NULL, NULL, inNumTransitionSteps ); mWorld->add( mFirstBlendedBlock ); mBlocks.push_back( mFirstBlendedBlock ); } delete blocksA; delete blocksB; } GridTransition::~GridTransition() { for( int i=0; iremove( block ); delete block; } } char GridTransition::isDone() { if( mFirstBlendedBlock == NULL ) { return true; } else { return mFirstBlendedBlock->isDone(); } } between-6+dfsg1.orig/game7/gameSource/upHint.png0000640000175000017500000000163111103112361020276 0ustar pabspabs‰PNG  IHDR‘h6PLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*TIDAT(ÏcdÈe 010ÐX 2§A¸—º†· è„à¢X4Àd™ð¨ ÁÕXõ0á±½ám¦&<þCcÓ+˜<`DNKÄDãàK|1+iK›©aIEND®B`‚between-6+dfsg1.orig/game7/gameSource/Player.h0000640000175000017500000000343611103751726017751 0ustar pabspabs#ifndef PLAYER_OBJECT_INCLUDED #define PLAYER_OBJECT_INCLUDED #include "GameObject.h" #include "common.h" class Player : public GameObject { public: Player(); ~Player(); // these three functions set values for all sprites in this object void setFlipHorizontal( char inFlip ) { for( int i=0; isetFlipHorizontal( inFlip ); } } void setHorizontalOffset( double inOffset ) { for( int i=0; isetHorizontalOffset( inOffset ); } } void setPage( int inPage ) { for( int i=0; isetPage( inPage ); } } // smooth blends to new position void shiftPosition( double inNewX, int inNumSteps ); // overrides GameObject functions virtual void step(); virtual void draw( double inRotation, Vector3D *inPosition, double inScale, double inFadeFactor, Color *inColor ); private: // main sprite is in GameObject::mSprite // white version of main sprite Sprite *mWhiteSprite; // brown version of main sprite Sprite *mBrownSprite; static const int mNumSprites = 3; // pointers to sprites Sprite *mSprites[mNumSprites]; char mShiftingPosition; double mShiftPositionA; double mShiftPositionB; int mNumShiftPositionSteps; int mNumShiftPositionStepsDone; }; #endif between-6+dfsg1.orig/game7/gameSource/Cloud.h0000640000175000017500000000160711103146352017552 0ustar pabspabs#ifndef CLOUD_OBJECT_INCLUDED #define CLOUD_OBJECT_INCLUDED #include "GameObject.h" class Cloud : public GameObject { public: Cloud(); // shifts between position, fade, and sprite of start and end clouds void shiftBetween( Cloud *inA, Cloud *inB, int inNumSteps ); // override draw function virtual void draw( double inRotation, Vector3D *inPosition, double inScale, double inFadeFactor, Color *inColor ); // override step function virtual void step(); double mBaseFade; protected: Cloud *mShiftA; Cloud *mShiftB; int mNumShiftSteps; int mNumShiftStepsDone; double mXSpeed; }; #endif between-6+dfsg1.orig/game7/gameSource/World.cpp0000640000175000017500000000507511377036601020141 0ustar pabspabs#include "World.h" World::~World() { int numObjects = mObjects.size(); for( int i=0; imDepthLayer > thisDepthLayer ) { thisDepthLayer = o->mDepthLayer; } } int nextDepthLayer = thisDepthLayer; thisDepthLayer += 1; // found with profiler // Construct one vector outside of loop Vector3D screenPos( 0, 0, 0 ); while( nextDepthLayer != thisDepthLayer ) { thisDepthLayer = nextDepthLayer; for( i=0; imDepthLayer == thisDepthLayer ) { // translate into screen coords screenPos.mX = ( o->mX - inScreenCenterX ) / numBlocksOnScreen; screenPos.mY = o->mY / numBlocksOnScreen + (0.5 / numBlocksOnScreen) - 0.5; double scale = o->mScale / numBlocksOnScreen; //printf( "Drawing sprite at %f,%f, %f\n", x, y, scale ); o->draw( o->mRotation, &screenPos, scale, o->mFadeFactor, &( o->mColor ) ); } else if( o->mDepthLayer < thisDepthLayer ) { if( nextDepthLayer == thisDepthLayer ) { nextDepthLayer = o->mDepthLayer; } else if( o->mDepthLayer > nextDepthLayer ) { nextDepthLayer = o->mDepthLayer; } } } } } void World::step() { int numObjects = mObjects.size(); for( int i=0; imEnableSteps ) { o->mainStep(); } } } between-6+dfsg1.orig/game7/gameSource/testBug.cpp0000640000175000017500000000062111106222563020451 0ustar pabspabs#include int main() { int A = 2; int B = 1; while( B != A ) { printf( "Start of loop, A=%d, B=%d\n", A, B ); A = B; printf( "Set A = B, so now A=%d, B=%d\n", A, B ); B = 0; printf( "Set B = 0, so now A=%d, B=%d\n", A, B ); } printf( "Loop ended because A and B equal, with A=%d, B=%d\n", A, B ); return 0; } between-6+dfsg1.orig/game7/gameSource/nextHint.png0000640000175000017500000000164411103077045020645 0ustar pabspabs‰PNG  IHDR‘h6PLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*_IDAT(Ï­RÁ ! ÂÆ nÎÛ…ÝÁŸWµ5!'O h ^ ð!"°}ïÕ³ý`¸‘AÄ ÁHF²Ì´f‰™&Í5fj¨)êâ&Áß=µºZ-…¿ ö‹4‰  J 'R¼ žIEND®B`‚between-6+dfsg1.orig/game7/gameSource/Timbre.cpp0000640000175000017500000001043111103404573020256 0ustar pabspabs#include "Timbre.h" #include "minorGems/util/stringUtils.h" #include #include double twelthRootOfTwo = pow( 2, 1.0/12 ); // for major scale // W, W, H, W, W, W, H int halfstepMap[ 7 ] = { 0, 2, 4, 5, 7, 9, 11 }; // minor scale // W,H,W,W,H,W,W //int halfstepMap[ 7 ] = { 0, 2, 3, 5, 7, 8, 10 }; // gets frequency of note in our scale double getFrequency( double inBaseFrequency, int inScaleNoteNumber ) { int octavesUp = inScaleNoteNumber / 7; int numHalfsteps = halfstepMap[ inScaleNoteNumber % 7 ] + octavesUp * 12; return inBaseFrequency * pow( twelthRootOfTwo, numHalfsteps ); } /* Was used during testing #include "minorGems/sound/formats/aiff.h" int outputFileNumber = 0; // outputs a wave table as an AIFF void outputWaveTable( Sint16 *inTable, int inLength, int inSampleRate ) { // generate the header int headerSize; unsigned char *aiffHeader = getAIFFHeader( 1, 16, inSampleRate, inLength, &headerSize ); char *fileName = autoSprintf( "waveTable%d.aiff", outputFileNumber ); outputFileNumber++; FILE *aiffFile = fopen( fileName, "wb" ); delete [] fileName; //printf( "Header size = %d\n", headerSize ); fwrite( aiffHeader, 1, headerSize, aiffFile ); delete [] aiffHeader; for( int i=0; i> 8 & 0xFF; unsigned char lsb = val && 0xFF; fwrite( &msb, 1, 1, aiffFile ); fwrite( &lsb, 1, 1, aiffFile ); } fclose( aiffFile ); } */ Timbre::Timbre( int inSampleRate, double inLoudness, double inBaseFrequency, int inNumWaveTableEntries, double( *inWaveFunction )( double ) ) : mNumWaveTableEntries( inNumWaveTableEntries ), mWaveTable( new Sint16*[ inNumWaveTableEntries ] ), mWaveTableLengths( new int[ inNumWaveTableEntries ] ) { // build wave table for each possible pitch in image for( int i=0; i maxValue ) { maxValue = waveValue; } else if( -waveValue > maxValue ) { maxValue = -waveValue; } } // now normalize and convert to int for( s=0; s tempUNIX2DOS.txt cp -f tempUNIX2DOS.txt "$1" rm -f tempUNIX2DOS.txtbetween-6+dfsg1.orig/game7/build/unix2dos.c0000640000175000017500000000035311103753137017261 0ustar pabspabs#include #include int main(void) { while(1) { int c = getchar(); if(c == EOF) exit(0); if(c == '\n') { putchar(015); /* ^M */ putchar(012); /* ^J */ } else { putchar(c); } } exit(0); } between-6+dfsg1.orig/game7/build/makeDistributions0000750000175000017500000000221411103760523020762 0ustar pabspabs#!/bin/sh # # Modification History # # 2007-November-12 Jason Rohrer # Copied from Cultivation build. # if [ $# -lt 2 ] ; then echo "Usage: $0 release_name unix_platform_name" exit 1 fi rm -rf unix rm -rf windows mkdir windows mkdir unix # work on unix tree first mkdir unix/Between mkdir unix/Between/graphics mkdir unix/Between/music mkdir unix/Between/settings mkdir unix/Between/languages cp ../gameSource/graphics/*.tga unix/Between/graphics cp ../gameSource/music/*.tga unix/Between/music cp ../gameSource/settings/*.ini unix/Between/settings cp ../gameSource/languages/*.txt unix/Between/languages cp ../gameSource/language.txt unix/Between cp ../documentation/Readme.txt unix/Between # duplicate unix tree so far to make windows tree cp -r unix/Between windows/ cp ../gameSource/Between unix/Between/ cp win32/Between.exe win32/*.dll windows/Between/ cd unix tar cf "Between_$1_$2.tar" Between gzip "Between_$1_$2.tar" cd .. g++ -o unix2dos unix2dos.c cp unix2dos windows cp unix2dosScript windows cd windows for file in Between/languages/*.txt do ./unix2dosScript "$file" done zip -r "Between_$1_Windows.zip" Between between-6+dfsg1.orig/game7/build/source/0000750000175000017500000000000011435543350016642 5ustar pabspabsbetween-6+dfsg1.orig/game7/build/source/runToBuild0000750000175000017500000000110211103756750020653 0ustar pabspabs#!/bin/bash # # Modification History # # 2007-November-12 Jason Rohrer # Copied from Cultivation. # cd game7 chmod u+x ./configure ./configure cd gameSource echo "Building Between..." make cd ../.. mkdir graphics mkdir music mkdir settings mkdir languages cp game7/gameSource/Between ./Between cp game7/documentation/Readme.txt . cp game7/gameSource/graphics/* ./graphics cp game7/gameSource/music/* ./music cp game7/gameSource/settings/* ./settings cp game7/gameSource/languages/* ./languages cp game7/gameSource/language.txt ./ echo "Run Between to play." between-6+dfsg1.orig/game7/build/source/makeSourceBuild0000750000175000017500000000117311435543060021646 0ustar pabspabs#!/bin/sh if [ $# -lt 1 ] ; then echo "Usage: $0 version_number" exit 1 fi echo "" echo " #### Removing any old Between_v$1_UnixSource directory ####" echo "" rm -rf Between_v$1_UnixSource* mkdir Between_v$1_UnixSource cd Between_v$1_UnixSource echo "" echo " #### Exporting source from repositories ####" echo "" ../exportSrc echo "" echo " #### Cleaning up unneeded source files ####" echo "" ../cleanSrc echo "" echo " #### Copying build script ####" echo "" cp ../runToBuild . echo "" echo " #### Making tarball ####" echo "" cd .. tar czf Between_v$1_UnixSource.tar.gz Between_v$1_UnixSource between-6+dfsg1.orig/game7/build/source/exportSrc0000750000175000017500000000061711435543060020563 0ustar pabspabs# Old CVS: # cvs -z3 -d:ext:jcr13@minorgems.cvs.sourceforge.net:/cvsroot/minorgems export -r HEAD minorGems # New Mercurial hg clone http://minorgems.hg.sourceforge.net/hgweb/minorgems/minorGems cd minorGems hg archive ../mgExport cd .. rm -r minorGems mv mgExport minorGems # Still using CVS for Between cvs -z3 -d:ext:jcr13@hcsoftware.cvs.sourceforge.net:/cvsroot/hcsoftware export -r HEAD game7between-6+dfsg1.orig/game7/build/source/cleanSrc0000750000175000017500000000060711435543060020323 0ustar pabspabsrm -r minorGems/ai rm -r minorGems/bench rm -r minorGems/doc rm -r minorGems/examples rm -r minorGems/sound rm -r minorGems/network/upnp rm -r minorGems/graphics/converters/lodepng.* rm -r game7/documentation/concept rm -r game7/documentation/html rm -r game7/documentation/igf2009 rm -r game7/documentation/esquire rm -r game7/documentation/screen_big.png rm -r game7/documentation/steam between-6+dfsg1.orig/game7/build/makeDistributionMacOSX0000750000175000017500000000222111103760523021610 0ustar pabspabs#!/bin/sh # # Modification History # # 2007-November-12 Jason Rohrer # Copied from Cultivation build. # if [ $# -lt 3 ] ; then echo "Usage: $0 release_name unix_platform_name path_to_SDL.framework" exit 1 fi rm -rf mac mkdir mac mkdir mac/Between mkdir mac/Between/graphics mkdir mac/Between/music mkdir mac/Between/settings mkdir mac/Between/languages cp ../gameSource/graphics/*.tga mac/Between/graphics cp ../gameSource/music/*.tga mac/Between/music cp ../gameSource/settings/*.ini mac/Between/settings cp ../gameSource/languages/*.txt mac/Between/languages cp ../gameSource/language.txt mac/Between cp ../documentation/Readme.txt mac/Between cp -r macOSX/Between.app mac/Between/Between.app cp ../gameSource/Between mac/Between/Between.app/Contents/MacOS rm -r mac/Between/Between.app/CVS rm -r mac/Between/Between.app/Contents/CVS rm -r mac/Between/Between.app/Contents/MacOS/CVS rm -r mac/Between/Between.app/Contents/Resources/CVS rm -r mac/Between/Between.app/Contents/Frameworks/CVS # install SDL framework cp -r $3 mac/Between/Between.app/Contents/Frameworks/ cd mac tar cf "Between_$1_$2.tar" Between gzip "Between_$1_$2.tar" between-6+dfsg1.orig/game7/build/win32/0000750000175000017500000000000011503620617016302 5ustar pabspabsbetween-6+dfsg1.orig/game7/build/win32/icon.png0000640000175000017500000000254111103754273017745 0ustar pabspabs‰PNG  IHDR üí£PLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*IDATHÇÅÖ¿oŽQðOõmU[^-ÕúÑ`e”ã,66B,‚Ø$,B"&‹QbÆf»‹? ƒDBÑŠ¤~Ô¶ÚîË=tîÓ;Ð@ ÊZözÃÎ\põ'x óŒ'ÅáWAÇ{0ž#à)«À†ƒrƒ¢6‚ËàZJ Hwܨý²“ØBí?köTÍ,†bíO×2u,4×P ò™Œt=ÁÙLÈ}¸ˆíµã{˜»­fU4h ó &ó±‚),?ÁcA†!(Œ-!àIx€í 9Îéõ…Õ€î'¸ð̆q5¤Þ†]¡Q•L_Wx£ÛCî Ô Làî@í» ¨¡ ŽþªýéðŠÒSdÅNššhç3ÒRªŒŸ SìÁÿ]v>\<ÆìcA9ƒ«1ŽÔ±”o…ÛõñTÛÍ]¦÷òûê²›vC~ÉwƒÒ¸¹¯?IEND®B`‚between-6+dfsg1.orig/game7/build/win32/icon.ico0000640000175000017500000000627611103764004017735 0ustar pabspabs ¨ ( @==>>DD::99@@==EEBB==>>DD::99@@==EEBBììéé22;;êêÑÑÝÝîîÓÓðð÷÷@@??KKììéé22;;êêÑÑÝÝîîÓÓðð÷÷@@??KKUUííõõÓÓÍÍÞÞèèòòóóââççççÌÌÜÜQQUUííõõÓÓÍÍÞÞèèòòóóââççççÌÌÜÜQQddêêîîççííááÔÔØØÚÚççïïÐи¸ÏÏêêhhddêêîîççííááÔÔØØÚÚççïïÐи¸ÏÏêêhhccÒÒììøøøøììÉɺºÁÁààââÖÖîîùùffccÒÒììøøøøììÉɺºÁÁààââÖÖîîùùffYYÁÁÖÖááøøõõááßßÓÓ¶¶ÁÁÇÇññõõggYYÁÁÖÖááøøõõááßßÓÓ¶¶ÁÁÇÇññõõgg``ÇÇÈÈÒÒññééééÍÍÅÅÞÞÔÔ¼¼ÝÝÍÍ[[``ÇÇÈÈÒÒññééééÍÍÅÅÞÞÔÔ¼¼ÝÝÍÍ[[YYÞÞÙÙééôôôô××ÜÜÛÛììûûîîÅÅÆÆººWWYYÞÞÙÙééôôôô××ÜÜÛÛììûûîîÅÅÆÆººWWeeÖÖââ÷÷ææ¸¸ÐÐÜÜîîõõóóÖÖææÜÜ]]eeÖÖââ÷÷ææ¸¸ÐÐÜÜîîõõóóÖÖææÜÜ]]ggïïääëëÑÑÙÙÝÝÏÏÌÌÌÌííîîééccggïïääëëÑÑÙÙÝÝÏÏÌÌÌÌííîîééccZZïïÞÞ××ËËÔÔííññÛÛµµÙÙ×׳³UUZZïïÞÞ××ËËÔÔííññÛÛµµÙÙ×׳³UUbbëëããÂÂËËââææççññÌ̯¯ÚÚÖÖÉÉ[[bbëëããÂÂËËââææççññÌ̯¯ÚÚÖÖÉÉ[[ZZÔÔ»»¬¬××ÍÍÅÅÙÙóóêêßßÏÏÁÁÂÂááWWZZÔÔ»»¬¬××ÍÍÅÅÙÙóóêêßßÏÏÁÁÂÂááWWaaÒÒÜÜÏÏÚÚÌ̶¶ÄÄä䨨ÝÝææÐÐååéé^^aaÒÒÜÜÏÏÚÚÌ̶¶ÄÄä䨨ÝÝææÐÐååéé^^ddÚÚÞÞ––››ÎÎÎÎÉÉÐÐââ““§§žžßß³³GGddÚÚÞÞ––››ÎÎÎÎÉÉÐÐââ““§§žžßß³³GG¢¢§§žž¤¤¢¢¥¥ƒƒzz¢¢§§žž¤¤¢¢¥¥ƒƒzzÃÀÿÃÀÿÀÀÀÀÀÀÀÀÀÀÀÀÀÀÃÀÃÃÀÃbetween-6+dfsg1.orig/game7/build/macOSX/0000750000175000017500000000000011435543350016474 5ustar pabspabsbetween-6+dfsg1.orig/game7/build/macOSX/dmgNotes.txt0000640000175000017500000000051711106470553021020 0ustar pabspabsTo mount dmg: hdiutil mount Test.dmg To unmount: hdiutil unmount /Volumes/Test To convert DMG to compressed: hdiutil convert Test.dmg -format UDZO -o Test_compressed.dmg To convert compressed DMG to R/W: hdiutil convert Test_compressed.dmg -format UDRW -o Test.dmg To rename a volume: diskutil rename /Volumes/NameA NameB between-6+dfsg1.orig/game7/build/macOSX/iconColor.png0000640000175000017500000000330311103755077021134 0ustar pabspabs‰PNG  IHDR€€L\öœPLTEÿÿÿÿÿÿÿÿÿÿÿÿÛÛÛ¶¶¶’’’mmmIII$$$Û¶’mI$Û¶’mI$ÛÛ¶¶’’mmII$$Û¶’mI$ÛÛ¶¶’’mmII$$ÛÛ¶¶’’mmII$$ÿÛÛÛ¶¶¶’’’mmmIII$$ÿ¶¶Û’’¶mm’IIm$$ÿ’’Ûmm¶II’$$ÿmmÛII¶$$ÿIIÛ$$ÿ$$ÛÿÛ¶Û¶’¶’m’mImI$I$¶ÿ¶’Û’m¶mI’I$m$’ÿ’mÛmI¶I$’$mÿmIÛI$¶$IÿI$Û$$ÿ$ÛÛÿ¶¶Û’’¶mm’IIm$$I¶¶ÿ’’Ûmm¶II’$$m’’ÿmmÛII¶$$’mmÿIIÛ$$¶IIÿ$$Û$$ÿÿÿÛÛÛ¶¶¶’’’mmmIII$ÿÿ¶ÛÛ’¶¶m’’Imm$ÿÿ’ÛÛm¶¶I’’$ÿÿmÛÛI¶¶$ÿÿIÛÛ$ÿÿ$ÿÛÿÛ¶Û¶’¶’m’mImI$Iÿ¶ÿÛ’Û¶m¶’I’m$mÿ’ÿÛmÛ¶I¶’$’ÿmÿÛIÛ¶$¶ÿIÿÛ$Ûÿ$ÿÛÿÿ¶ÛÛ’¶¶m’’Imm$II¶ÿÿ’ÛÛm¶¶I’’$mm’ÿÿmÛÛI¶¶$’’mÿÿIÛÛ$¶¶Iÿÿ$ÛÛ$ÿÿÿÛ¶Û¶’¶’m’mImI$I$ÿ¶’Û’m¶mI’I$m$ÿ¶ÛÛ’¶¶m’’Imm$II$ÿ’¶Ûm’¶Im’$Im$Û¶ÿ¶’Û’m¶mI’I$m$I¶’ÿ’mÛmI¶I$’$m¶Ûÿ’¶Ûm’¶Im’$Im$I’¶ÿm’ÛIm¶$I’$m¶ÿÛ’Û¶m¶’I’m$mII$’ÿ¶mÛ’I¶m$’Im$Ûÿ¶¶Û’’¶mm’IIm$$I¶ÿ’’Ûmm¶II’$$mÿ¶Û’¶m’Iÿ¶Û’¶m’I¶ÿ’Ûm¶I’Ï*~IDATxÚí¿oNQÆoõÕÒª—*õ«ÁÊ(!Æ;Xll„X1°IX„D:ÙXŒ36ÛYü$‚ˆIýhK[¼þûžDÒ[>ÏøÜûÞ÷¾ýôœœçœï¹·¯”R5©žªýjS³]&š¯Cª§áúßáÍö½“Í~?\f{Éî“ô¤®£Û? ß»ªRË*@JPø?ÕW#—Áï€ÿüÕàïït©Ùž:ØìÂe?Ve±RLõ üÛ¶» %(@  =êT¿àÈð‡À?þ0ø_Áÿþúlü> þð׆·ËÕðÇmvAJP€@›rÀBˆæø_Àß~øÝ*ðwÃqúø¸Bþ.ðlvAJP€@›rÀ82ŽÓ)̆×ïd¹á7œþü·a\ÿøWÁ?ïþ» %(@  E9 œ‚}— þ\i'ø4NðT ³-ûaÝðk{YüÀz¡E[€]€” °r ¯4^‡Ì´¯øs³ýN§m´ 1æÚ‡üÐ`¤ %(¬ä@7ïÁ_ú›Á þÖ,fÐ8}0ü¹TG´ü+à_‡çŒÚì‚  %¨åÈõ]¨ÿ¹ ŸX Ø41ÏÿÁ¶°NÐ Çõ´lAõþ3àÃòn‡X´Ø)@ @J-Êå,ì¸ùà\8` Çû£ÙH?JÛ æÁ§÷ì ãPÇ`¤ %(´(àÚßKÛTç3ü—ÌŸ²Ø@óòÏÃÛ$Ÿö@ù–GÙì‚  %¨VåšÇßþ–pL¢ øéfûE3ö†ÿ‰”'¨Ü‰ÃÚ³Ø)@ @J-Êõ}¨ÿ™ “­Ì…l*Ô‡î†ÓGÂqúë,~àÏÝþ§Ûì‚  %¨åÈøà~ði¢ýøTGDë TpëTï?þ!èy¢?ÜAÛ'.ú1» %(@  E9 \€}Â=X' yüÓàÓ{Á€>—”_Dñf"Œ7ÇÁïe·i ° R€€”Z•ðÈQðáÅZåV‰¾¸>9c>xƒÓÓú}:ÿZ)¶» %(@ à_ÓX‡„’QñÏIEND®B`‚between-6+dfsg1.orig/game7/build/macOSX/Between.app/0000750000175000017500000000000011435543350020644 5ustar pabspabsbetween-6+dfsg1.orig/game7/build/macOSX/Between.app/Contents/0000750000175000017500000000000011435543350022441 5ustar pabspabsbetween-6+dfsg1.orig/game7/build/macOSX/Between.app/Contents/PkgInfo0000640000175000017500000000001011103755573023715 0ustar pabspabsAPPL????between-6+dfsg1.orig/game7/build/macOSX/Between.app/Contents/Info.plist0000640000175000017500000000177211103755573024425 0ustar pabspabs CFBundleInfoDictionaryVersion 6.0 CFBundleIdentifier org.passage CFBundleDevelopmentRegion English CFBundleExecutable Between CFBundleIconFile Between.icns CFBundleName Between CFBundlePackageType APPL CFBundleSignature ???? CFBundleVersion 0 CFBundleShortVersionString 0 CFBundleGetInfoString Between CFBundleLongVersionString 0 NSHumanReadableCopyright Public Domain, 2008 LSRequiresCarbon CSResourcesFileMapped between-6+dfsg1.orig/game7/build/macOSX/Between.app/Contents/Resources/0000750000175000017500000000000011435543350024413 5ustar pabspabsbetween-6+dfsg1.orig/game7/build/macOSX/Between.app/Contents/Resources/Between.rsrc0000640000175000017500000000552711103755573026715 0ustar pabspabs §§°;)This application needs at least a MacPlus"This application needs more memory!This application is out of memory*This application needs at least System 8.6 About this wxWindows Application}This application needs Appearance extension (built in with System 8) - this restriction will be relieved in the final release"ÿÿÿýAboutÉ-Dà01Æ#b""#b1Æ0ààðøü?þ?þ?þ?þ?þüøðàDDðˆp @@€€ðøøððàÀÀ€€D!@€@€@€@€!€Ààp8?€ÿÀÿÀÿÀÿÀÿÀÀ?àðø|>Dàð88< ngc†aÆ`æpv0<øà@ð?ø<<~ÿo†çÇcæá÷pþp~<<üð@D€€€€€€àððððPPPÀÀÀÀÀÀàð?ø?ø?ø?ø?ø?ø?ø?ø DÀ@@À1€Gþ€€þ€@À@ÀÀ€?€ÀÀÀÀ?€þÿÿÿÿÿþÿÀÿÀÿÀÿÀÿ€?€D€`Œ €€Àø€àðüÿÿÿÿÿÿÿÿÿÿÿÿøD@x`üqÎy†|~¸|0l0F00ÀxàüñþûÿÿÏÿÿÿ¾ÿüþxÿxïøÏø‡øøD>~þþ>6b`ÀÀ?ÿÿÿÿ÷óáàÀD€Àà€€€üü€€€àÀ€€ÀàðøÀ?þ?þ?þ?þÀøðàÀ€D€Àà€ˆŒ?þŒˆ€àÀ€€Ààð èÜ?þÿ?þÜ èðàÀ€D Ààp8?—ãá!ð1ø:|<<>??€ Dxpp`HàÀ€€H88xþüøpððéðÇà‡À„Œ>\<<8|üüD @øô *¨ð€8`€>|pàü?ööþüø?ðÀøà AÀ¢ð¥üKÿ×ÿÀñÿÿðàÿü€ÿÿÿ€ÿÿÿ€?ÿþ€ÿÿþ€?ÿúÀÿÿöÿÿî_ÿÿÞÿÿÿ¾Ïÿÿóÿþÿäÿýþá?ûüàO÷øàïðxßà?À€?€à?x><¸ð`AÀãðçüÏÿßÿÀÿÿÿðÿÿÿüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿüÿÿÿøÿÿÿðÿÿàÿÿÀÿÿ€ÿÿþüøð`@ ÀðëüŽÿ¯þ—þßþïú¿ç‹æÅÜ0Ø0`À Àðÿüÿÿÿÿÿÿÿÿÿÿÿÿÿþÿü?øðàÀ€ì oÀÞ½ÖfoÀÞ»îeffoÀâ;»fffnì,¥ffff`á¦ffffн½æfffmÀÿöffff\Àìßfffm ÿü ßffPßü]À ßm ÿÀ uÀ Ðßü mÀ ÿÀÎeÏüÝoÀõ÷ëñ+õøˆ‚VÒÒÒìñøùû^^ý‚ï°ìÒÒÒìñ÷õ­]33^‡^‚ÓÒÒÒÒÒëý‚33¬ÕÒëÒÒÒÒÒÒÒõˆ33_ïÒÒÒÒÒÒÒÒ€û^]]ÕÒÒÒÒÒÒÒÒ€öýÿÖìÒÒÒÒÒÒÒÒ€++õþ÷ôïëÒÒÒÒÒ€öùÿýþö+WþðëÒÒ€öVÿÿ÷~ªö÷Wóì€+Vÿÿ÷1͆ö÷ú+Vÿÿ÷õzë€öVÿÿ÷*«ì€+ÿÿ÷[«ðý÷š STR#RMENU^MBARjcarbvldes‚CURSšICN#Nics#Zics4fics8r€ÿÿ?ÿÿeÿÿm€ÿÿsÿÿ‰ ÿÿŸ ÿÿç ÿÿ/ ÿÿwÿÿ¿ÿÿÿÿOÿÿ—ÿÿßÿÿ'ÿÿoÿÿ·ÿÿÿÿÿGÿÿ€ÿÿ×€ÿÿÛ€ÿÿ€ÿÿ£Simple Alert Messagesbetween-6+dfsg1.orig/game7/build/macOSX/Between.app/Contents/Resources/Between.icns0000640000175000017500000005201411104012405026646 0ustar pabspabsicnsT it32ü…²²•…’…••²…p…g²²•…’…••²…p…g²²•…’…••²…p…g²²•…’…••²…p…g²²•…’…••²…p…g²²•…’…••²…p…g²²•…’…••²…p…g²²•…’…••²…p…g…²½…Æ…Ü……—……Ø…¥…5½…Æ…Ü……—……Ø…¥…5½…Æ…Ü……—……Ø…¥…5½…Æ…Ü……—……Ø…¥…5½…Æ…Ü……—……Ø…¥…5½…Æ…Ü……—……Ø…¥…5½…Æ…Ü……—……Ø…¥…5½…Æ…Ü……—……Ø…¥…5½…Þ…Ð…Ö…à…Æ…ß…ä…J½…Þ…Ð…Ö…à…Æ…ß…ä…J½…Þ…Ð…Ö…à…Æ…ß…ä…J½…Þ…Ð…Ö…à…Æ…ß…ä…J½…Þ…Ð…Ö…à…Æ…ß…ä…J½…Þ…Ð…Ö…à…Æ…ß…ä…J½…Þ…Ð…Ö…à…Æ…ß…ä…J½…Þ…Ð…Ö…à…Æ…ß…ä…J½…ð…å…Ø…Å…µ…¶…Ú…D½…ð…å…Ø…Å…µ…¶…Ú…D½…ð…å…Ø…Å…µ…¶…Ú…D½…ð…å…Ø…Å…µ…¶…Ú…D½…ð…å…Ø…Å…µ…¶…Ú…D½…ð…å…Ø…Å…µ…¶…Ú…D½…ð…å…Ø…Å…µ…¶…Ú…D½…ð…å…Ø…Å…µ…¶…Ú…D½…î…Â… …Ò…Í…¾…G…²½…î…Â… …Ò…Í…¾…G…²½…î…Â… …Ò…Í…¾…G…²½…î…Â… …Ò…Í…¾…G…²½…î…Â… …Ò…Í…¾…G…²½…î…Â… …Ò…Í…¾…G…²½…î…Â… …Ò…Í…¾…G…²½…î…Â… …Ò…Í…¾…G²µ…î…Ó…§…Ñ…Ï…¥…B²µ…î…Ó…§…Ñ…Ï…¥…B²µ…î…Ó…§…Ñ…Ï…¥…B²µ…î…Ó…§…Ñ…Ï…¥…B²µ…î…Ó…§…Ñ…Ï…¥…B²µ…î…Ó…§…Ñ…Ï…¥…B²µ…î…Ó…§…Ñ…Ï…¥…B²µ…î…Ó…§…Ñ…Ï…¥…B²µ…ÅÂ…é…ê…ä…O²µ…ÅÂ…é…ê…ä…O²µ…ÅÂ…é…ê…ä…O²µ…ÅÂ…é…ê…ä…O²µ…ÅÂ…é…ê…ä…O²µ…ÅÂ…é…ê…ä…O²µ…ÅÂ…é…ê…ä…O²µ…ÅÂ…é…ê…ä…O²µ…Õ…ê…ó…ð…Í…à…Õ…I…²µ…Õ…ê…ó…ð…Í…à…Õ…I…²µ…Õ…ê…ó…ð…Í…à…Õ…I…²µ…Õ…ê…ó…ð…Í…à…Õ…I…²µ…Õ…ê…ó…ð…Í…à…Õ…I…²µ…Õ…ê…ó…ð…Í…à…Õ…I…²µ…Õ…ê…ó…ð…Í…à…Õ…I…²µ…Õ…ê…ó…ð…Í…à…Õ…I½…Ó…è…ú…ê…¹…»…­…D½…Ó…è…ú…ê…¹…»…­…D½…Ó…è…ú…ê…¹…»…­…D½…Ó…è…ú…ê…¹…»…­…D½…Ó…è…ú…ê…¹…»…­…D½…Ó…è…ú…ê…¹…»…­…D½…Ó…è…ú…ê…¹…»…­…D½…Ó…è…ú…ê…¹…»…­…D…²µ…Ã…¹…×…Ë…¯…Ö…Ã…G…²µ…Ã…¹…×…Ë…¯…Ö…Ã…G…²µ…Ã…¹…×…Ë…¯…Ö…Ã…G…²µ…Ã…¹…×…Ë…¯…Ö…Ã…G…²µ…Ã…¹…×…Ë…¯…Ö…Ã…G…²µ…Ã…¹…×…Ë…¯…Ö…Ã…G…²µ…Ã…¹…×…Ë…¯…Ö…Ã…G…²µ…Ã…¹…×…Ë…¯…Ö…Ã…G…²µ…Ø…Ê…¨…µ…¼…î…ó…S…²µ…Ø…Ê…¨…µ…¼…î…ó…S…²µ…Ø…Ê…¨…µ…¼…î…ó…S…²µ…Ø…Ê…¨…µ…¼…î…ó…S…²µ…Ø…Ê…¨…µ…¼…î…ó…S…²µ…Ø…Ê…¨…µ…¼…î…ó…S…²µ…Ø…Ê…¨…µ…¼…î…ó…S…²µ…Ø…Ê…¨…µ…¼…î…ó…S…²µ…­…µ…Ù…Ü…Í…ê…ø…R…²µ…­…µ…Ù…Ü…Í…ê…ø…R…²µ…­…µ…Ù…Ü…Í…ê…ø…R…²µ…­…µ…Ù…Ü…Í…ê…ø…R…²µ…­…µ…Ù…Ü…Í…ê…ø…R…²µ…­…µ…Ù…Ü…Í…ê…ø…R…²µ…­…µ…Ù…Ü…Í…ê…ø…R…²µ…­…µ…Ù…Ü…Í…ê…ø…R½…Ò…â…ë…Æ…ª…Å…å…T½…Ò…â…ë…Æ…ª…Å…å…T½…Ò…â…ë…Æ…ª…Å…å…T½…Ò…â…ë…Æ…ª…Å…å…T½…Ò…â…ë…Æ…ª…Å…å…T½…Ò…â…ë…Æ…ª…Å…å…T½…Ò…â…ë…Æ…ª…Å…å…T½…Ò…â…ë…Æ…ª…Å…å…T½…ð…Üâ…Â…Õ…>…²½…ð…Üâ…Â…Õ…>…²½…ð…Üâ…Â…Õ…>…²½…ð…Üâ…Â…Õ…>…²½…ð…Üâ…Â…Õ…>…²½…ð…Üâ…Â…Õ…>…²½…ð…Üâ…Â…Õ…>…²½…ð…Üâ…Â…Õ…>²µ…ê…Ê…í…õ….…-…8²µ…ê…Ê…í…õ….…-…8²µ…ê…Ê…í…õ….…-…8²µ…ê…Ê…í…õ….…-…8²µ…ê…Ê…í…õ….…-…8²µ…ê…Ê…í…õ….…-…8²µ…ê…Ê…í…õ….…-…8²µ…ê…Ê…í…õ….…-…8²²•….…,…3…0¥²²•….…,…3…0¥²²•….…,…3…0¥²²•….…,…3…0¥²²•….…,…3…0¥²²•….…,…3…0¥²²•….…,…3…0¥²²•….…,…3…0²…²…}…’²…—……”•²²…}…’²…—……”•²²…}…’²…—……”•²²…}…’²…—……”•²²…}…’²…—……”•²²…}…’²…—……”•²²…}…’²…—……”•²²…}…’²…—……”•²…²…P…Ò…×…„…ŠÄ…¾½…P…Ò…×…„…ŠÄ…¾½…P…Ò…×…„…ŠÄ…¾½…P…Ò…×…„…ŠÄ…¾½…P…Ò…×…„…ŠÄ…¾½…P…Ò…×…„…ŠÄ…¾½…P…Ò…×…„…ŠÄ…¾½…P…Ò…×…„…ŠÄ…¾½…M…É…Õ…Å…Ò…Â…¨…¸½…M…É…Õ…Å…Ò…Â…¨…¸½…M…É…Õ…Å…Ò…Â…¨…¸½…M…É…Õ…Å…Ò…Â…¨…¸½…M…É…Õ…Å…Ò…Â…¨…¸½…M…É…Õ…Å…Ò…Â…¨…¸½…M…É…Õ…Å…Ò…Â…¨…¸½…M…É…Õ…Å…Ò…Â…¨…¸½…F…Ë…®……Ï…Ã…¹…ѽ…F…Ë…®……Ï…Ã…¹…ѽ…F…Ë…®……Ï…Ã…¹…ѽ…F…Ë…®……Ï…Ã…¹…ѽ…F…Ë…®……Ï…Ã…¹…ѽ…F…Ë…®……Ï…Ã…¹…ѽ…F…Ë…®……Ï…Ã…¹…ѽ…F…Ë…®……Ï…Ã…¹…ѽ…N…ç…Ý…¶…À…Ü…à…âµ…²…N…ç…Ý…¶…À…Ü…à…âµ…²…N…ç…Ý…¶…À…Ü…à…âµ…²…N…ç…Ý…¶…À…Ü…à…âµ…²…N…ç…Ý…¶…À…Ü…à…âµ…²…N…ç…Ý…¶…À…Ü…à…âµ…²…N…ç…Ý…¶…À…Ü…à…âµ…²…N…ç…Ý…¶…À…Ü…à…âµ²…F…ë…×…Ï…À…Ë…éµ²…F…ë…×…Ï…À…Ë…éµ²…F…ë…×…Ï…À…Ë…éµ²…F…ë…×…Ï…À…Ë…éµ²…F…ë…×…Ï…À…Ë…éµ²…F…ë…×…Ï…À…Ë…éµ²…F…ë…×…Ï…À…Ë…éµ²…F…ë…×…Ï…À…Ë…éµ²…S…ë…Þ…ç…Ç…Ñ…Öµ²…S…ë…Þ…ç…Ç…Ñ…Öµ²…S…ë…Þ…ç…Ç…Ñ…Öµ²…S…ë…Þ…ç…Ç…Ñ…Öµ²…S…ë…Þ…ç…Ç…Ñ…Öµ²…S…ë…Þ…ç…Ç…Ñ…Öµ²…S…ë…Þ…ç…Ç…Ñ…Öµ²…S…ë…Þ…ç…Ç…Ñ…Öµ²…Q…Í…Ü…õ…à…ª…ƽ…²…Q…Í…Ü…õ…à…ª…ƽ…²…Q…Í…Ü…õ…à…ª…ƽ…²…Q…Í…Ü…õ…à…ª…ƽ…²…Q…Í…Ü…õ…à…ª…ƽ…²…Q…Í…Ü…õ…à…ª…ƽ…²…Q…Í…Ü…õ…à…ª…ƽ…²…Q…Í…Ü…õ…à…ª…ƽ…F…×…Ñ…äñ…Ï…Õ½…F…×…Ñ…äñ…Ï…Õ½…F…×…Ñ…äñ…Ï…Õ½…F…×…Ñ…äñ…Ï…Õ½…F…×…Ñ…äñ…Ï…Õ½…F…×…Ñ…äñ…Ï…Õ½…F…×…Ñ…äñ…Ï…Õ½…F…×…Ñ…äñ…Ï…Õ½…²…L…¼…½…É…îä½…²…L…¼…½…É…îä½…²…L…¼…½…É…îä½…²…L…¼…½…É…îä½…²…L…¼…½…É…îä½…²…L…¼…½…É…îä½…²…L…¼…½…É…îä½…²…L…¼…½…É…îä½…²…F…µ…Í…Ú…ö…ó…Ú½…²…F…µ…Í…Ú…ö…ó…Ú½…²…F…µ…Í…Ú…ö…ó…Ú½…²…F…µ…Í…Ú…ö…ó…Ú½…²…F…µ…Í…Ú…ö…ó…Ú½…²…F…µ…Í…Ú…ö…ó…Ú½…²…F…µ…Í…Ú…ö…ó…Ú½…²…F…µ…Í…Ú…ö…ó…Ú½…²…O…É…èö…è…¾½…²…O…É…èö…è…¾½…²…O…É…èö…è…¾½…²…O…É…èö…è…¾½…²…O…É…èö…è…¾½…²…O…É…èö…è…¾½…²…O…É…èö…è…¾½…²…O…É…èö…è…¾½…P…å…ê…â…é…څ˅н…P…å…ê…â…é…څ˅н…P…å…ê…â…é…څ˅н…P…å…ê…â…é…څ˅н…P…å…ê…â…é…څ˅н…P…å…ê…â…é…څ˅н…P…å…ê…â…é…څ˅н…P…å…ê…â…é…څ˅н…B…é…ó…Ê…Ã…×…ã…ïµ…²…B…é…ó…Ê…Ã…×…ã…ïµ…²…B…é…ó…Ê…Ã…×…ã…ïµ…²…B…é…ó…Ê…Ã…×…ã…ïµ…²…B…é…ó…Ê…Ã…×…ã…ïµ…²…B…é…ó…Ê…Ã…×…ã…ïµ…²…B…é…ó…Ê…Ã…×…ã…ïµ…²…B…é…ó…Ê…Ã…×…ã…ïµ²…è…ä…"…*…å…Ç…Öµ²…è…ä…"…*…å…Ç…Öµ²…è…ä…"…*…å…Ç…Öµ²…è…ä…"…*…å…Ç…Öµ²…è…ä…"…*…å…Ç…Öµ²…è…ä…"…*…å…Ç…Öµ²…è…ä…"…*…å…Ç…Öµ²…è…ä…"…*…å…Ç…Öµ²,²…2…)…(¥²,²…2…)…(¥²,²…2…)…(¥²,²…2…)…(¥²,²…2…)…(¥²,²…2…)…(¥²,²…2…)…(¥²,²…2…)…(²…²²¥•²²²¥•²²²¥•²²²¥•²²²¥•²²²¥•²²²¥•²²²¥•²…²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÅ…²õ…²õ…²õ…²õ…²õ…²õ…²õ²í²í²í²í²í²í²í²í²í²í²í²í²í²í²í²í²õ…²õ…²õ…²õ…²õ…²õ…²õ…²ÿÿÿÿÿÿÿÿå…²õ…²õ…²õ…²õ…²õ…²õ…²õ…²õ…²õ…²õ…²õ…²õ…²õ…²õ…²õ…²õ…²õ…²õ…²õ…²õ…²õ…²õ…²õ…²ÿÿÿÿÿÿÿÿÿÛ…²õ…²õ…²õ…²õ…²õ…²õ…²õ²í²í²í²í²í²í²í²í²²µ¥²²µ¥²²µ¥²²µ¥²²µ¥²²µ¥²²µ¥²²µ²t8mk@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿbetween-6+dfsg1.orig/game7/build/macOSX/iconMask.png0000640000175000017500000000044511104012200020724 0ustar pabspabs‰PNG  IHDR€€L\öœìIDATxÚíÝ[ € @Q'Úÿ–mÍÇ€˜æ9 °ÇEABŠÞ{{­"'S”ê}ŽºÿìºWãS €ÿ^ÁÎ,J@àL÷¨s˜ € € € ,ëö æÈ¾¯˜– @€ Âù;a@@@@@¶çÀ$þ#¶(@€3ù˜ € Àû€Qeû‰Ì.ûŒês™– @€ <{©!¬K>||IEND®B`‚between-6+dfsg1.orig/game7/configure0000750000175000017500000000305311062263107016146 0ustar pabspabs#!/bin/bash # # Modification History # # 2006-June-27 Jason Rohrer # Copied/modified from Transcend project. Dropped a platforms that were only # nominally supported. # while [ -z "$platformSelection" ] do echo "select platform:" echo " 1 -- GNU/Linux" echo " 2 -- MacOSX" echo " 3 -- Win32 using MinGW" echo " q -- quit" echo "" echo -n "> " read platformSelection if [ "$platformSelection" = "q" ] then exit fi # use ASCII comparison. if [[ "$platformSelection" > "3" ]] then platformSelection="" fi if [[ "$platformSelection" < "1" ]] then platformSelection="" fi done # use partial makefiles from minorGems project makefileMinorGems="../minorGems/build/Makefile.minorGems" makefileMinorGemsTargets="../minorGems/build/Makefile.minorGems_targets" platformName="Generic" platformMakefile="generic" case "$platformSelection" in "1" ) platformName="GNU/Linux" platformMakefile="Makefile.GnuLinux" ;; "2" ) platformName="MacOSX" platformMakefile="Makefile.MacOSX" ;; "3" ) platformName="Win32 MinGW" platformMakefile="Makefile.MinGW" ;; esac rm -f Makefile.temp echo "# Auto-generated by game7/configure for the $platformName platform. Do not edit manually." > Makefile.temp rm -f gameSource/Makefile cat Makefile.temp $platformMakefile Makefile.common $makefileMinorGems gameSource/Makefile.all $makefileMinorGemsTargets > gameSource/Makefile rm Makefile.temp exit between-6+dfsg1.orig/game7/Makefile.common0000640000175000017500000000250011377036601017171 0ustar pabspabs# # Modification History # # 2004-April-30 Jason Rohrer # Created. Modified from MUTE source. # # 2005-August-29 Jason Rohrer # Added optimization options. # # 2007-April-23 Jason Rohrer # Upgraded to latest minorGems dependency format. # ## # The common portion of all Makefiles. # Should not be made manually---used by configure to build Makefiles. ## EXE_LINKER = ${GXX} RANLIB = ranlib LIBRARY_LINKER = ar DEBUG_ON_FLAG = -g #-DDEBUG_MEMORY DEBUG_OFF_FLAG = DEBUG_FLAG = ${DEBUG_ON_FLAG} PROFILE_ON_FLAG = -pg -DUSE_GPROF_THREADS PROFILE_OFF_FLAG = PROFILE_FLAG = ${PROFILE_OFF_FLAG} OPTIMIZE_ON_FLAG = -O9 OPTIMIZE_OFF_FLAG = -O0 OPTIMIZE_FLAG = ${OPTIMIZE_OFF_FLAG} PORT_AUDIO_PATH = ${ROOT_PATH}/minorGems/sound/portaudio # common to all platforms SOCKET_UDP_PLATFORM_PATH = unix SOCKET_UDP_PLATFORM = Unix COMPILE_FLAGS = -Wall -Wwrite-strings -Wchar-subscripts -Wparentheses ${DEBUG_FLAG} ${PLATFORM_COMPILE_FLAGS} ${PROFILE_FLAG} ${OPTIMIZE_FLAG} -I${ROOT_PATH} COMPILE = ${GXX} ${COMPILE_FLAGS} -c EXE_LINK = ${EXE_LINKER} ${COMPILE_FLAGS} ${LINK_FLAGS} LIBRARY_LINK = ${LIBRARY_LINKER} cru # # Generic: # # Map all .cpp C++ and C files into .o object files # # $@ represents the name.o file # $< represents the name.cpp file # .cpp.o: ${COMPILE} -o $@ $< .c.o: ${COMPILE} -o $@ $< between-6+dfsg1.orig/game7/Makefile.MinGW0000640000175000017500000000155111106466065016670 0ustar pabspabs# # Modification History # # 2003-November-2 Jason Rohrer # Created. # # 2003-November-10 Jason Rohrer # Removed pthread flag. # Changed LINUX flag to WIN_32 flag. # Added wsock32 library flag. # ## # The common MinGW (GNU for Win32) portion of Makefiles. # Should not be made manually---used by configure to build Makefiles. ## PLATFORM_COMPILE_FLAGS = -DWIN_32 # need various GL libraries, winmm, and portaudio # -mwindows tells mingw to hide the dos command window on launch PLATFORM_LINK_FLAGS = -lopengl32 -lglu32 -lmingw32 -lSDLmain -lSDL -mwindows -lwsock32 # All platforms but OSX support g++ and need no linker hacks GXX = g++ LINK_FLAGS = ## # Platform-specific minorGems file path prefixes ## PLATFORM = Win32 PLATFORM_PATH = win32 TIME_PLATFORM = Win32 TIME_PLATFORM_PATH = win32 DIRECTORY_PLATFORM = Win32 DIRECTORY_PLATFORM_PATH = win32 between-6+dfsg1.orig/game7/server/0000750000175000017500000000000011435543354015555 5ustar pabspabsbetween-6+dfsg1.orig/game7/server/server.php0000640000175000017500000011201611104202675017565 0ustar pabspabs Game 7 Server Web-based setup
"; $setup_footer = "
"; // ensure that magic quotes are on (adding slashes before quotes // so that user-submitted data can be safely submitted in DB queries) if( !get_magic_quotes_gpc() ) { // force magic quotes to be added $_GET = array_map( 'gs_addslashes_deep', $_GET ); $_POST = array_map( 'gs_addslashes_deep', $_POST ); $_REQUEST = array_map( 'gs_addslashes_deep', $_REQUEST ); $_COOKIE = array_map( 'gs_addslashes_deep', $_COOKIE ); } // all calls need to connect to DB, so do it once here gs_connectToDatabase(); // close connection down below (before function declarations) // testing: //sleep( 5 ); // general processing whenver server.php is accessed directly gs_checkForFlush(); // grab POST/GET variables $action = ""; if( isset( $_REQUEST[ "action" ] ) ) { $action = $_REQUEST[ "action" ]; } $debug = ""; if( isset( $_REQUEST[ "debug" ] ) ) { $debug = $_REQUEST[ "debug" ]; } if( $action == "version" ) { global $gs_version; echo "$gs_version"; } else if( $action == "show_log" ) { gs_showLog(); } else if( $action == "clear_log" ) { gs_clearLog(); } else if( $action == "get_player_id" ) { gs_getPlayerID(); } else if( $action == "create_for_friend" ) { gs_createForFriend(); } else if( $action == "join_with_friend" ) { gs_joinWithFriend(); } else if( $action == "join_with_stranger" ) { gs_joinWithStranger(); } else if( $action == "is_partner_ready" ) { gs_isPartnerReady(); } else if( $action == "report_alive" ) { gs_reportAlive(); } else if( $action == "post_move" ) { gs_postMove(); } else if( $action == "get_changed_columns" ) { gs_getChangedColumns(); } else if( $action == "gs_setup" ) { global $setup_header, $setup_footer; echo $setup_header; echo "

Game 7 Server Web-based Setup

"; echo "Creating tables:
"; echo "
"; gs_setupDatabase(); echo "


"; echo $setup_footer; } else if( preg_match( "/server\.php/", $_SERVER[ "SCRIPT_NAME" ] ) ) { // server.php has been called without an action parameter // the preg_match ensures that server.php was called directly and // not just included by another script // quick (and incomplete) test to see if we should show instructions global $tableNamePrefix; // check if our "games" table exists $tableName = $tableNamePrefix . "games"; $exists = gs_doesTableExist( $tableName ); if( $exists ) { echo "Game 7 server database setup and ready"; } else { // start the setup procedure global $setup_header, $setup_footer; echo $setup_header; echo "

Game 7 Server Web-based Setup

"; echo "Game 7 Server will walk you through a " . "brief setup process.

"; echo "Step 1: ". "". "create the database tables"; echo $setup_footer; } } // done processing // only function declarations below gs_closeDatabase(); /** * Creates the database tables needed by seedBlogs. */ function gs_setupDatabase() { global $tableNamePrefix; $tableName = $tableNamePrefix . "server_globals"; if( ! gs_doesTableExist( $tableName ) ) { // this table contains general info about the server // use INNODB engine so table can be locked $query = "CREATE TABLE $tableName(" . "next_player_id CHAR(7) NOT NULL, ". "last_flush_time DATETIME NOT NULL ) ENGINE = INNODB;"; $result = gs_queryDatabase( $query ); echo "$tableName table created
"; } else { echo "$tableName table already exists
"; } $tableName = $tableNamePrefix . "log"; if( ! gs_doesTableExist( $tableName ) ) { // this table contains general info about the server // use INNODB engine so table can be locked $query = "CREATE TABLE $tableName(" . "entry TEXT NOT NULL, ". "entry_time DATETIME NOT NULL );"; $result = gs_queryDatabase( $query ); echo "$tableName table created
"; } else { echo "$tableName table already exists
"; } $tableName = $tableNamePrefix . "games"; if( ! gs_doesTableExist( $tableName ) ) { // this table contains general info about each game // use INNODB engine so table can be locked $query = "CREATE TABLE $tableName(" . "game_id CHAR(7) NOT NULL PRIMARY KEY," . "game_passcode CHAR(32) NOT NULL," . "private TINYINT NOT NULL," . "creation_date DATETIME NOT NULL," . "touch_date DATETIME NOT NULL," . "player_1_id CHAR(7) NOT NULL," . "player_2_id CHAR(7) NOT NULL," . "player_1_transform CHAR(37) NOT NULL," . "player_2_transform CHAR(37) NOT NULL," . "player_1_ready TINYINT NOT NULL," . "player_2_ready TINYINT NOT NULL," . "player_1_touch_date DATETIME NOT NULL," . "player_2_touch_date DATETIME NOT NULL," . "state_number INT NOT NULL ) ENGINE = INNODB;"; $result = gs_queryDatabase( $query ); echo "$tableName table created
"; } else { echo "$tableName table already exists
"; } $tableName = $tableNamePrefix . "columns"; if( ! gs_doesTableExist( $tableName ) ) { // this table contains information for each user $query = "CREATE TABLE $tableName(" . "game_id CHAR(7) NOT NULL," . "column_index TINYINT NOT NULL," . "blocks TEXT NOT NULL," . "changed_in_state INT NOT NULL, ". "PRIMARY KEY( game_id, column_index ) );"; $result = gs_queryDatabase( $query ); echo "$tableName table created
"; } else { echo "$tableName table already exists
"; } } function gs_showLog() { $password = ""; if( isset( $_REQUEST[ "password" ] ) ) { $password = $_REQUEST[ "password" ]; } global $logAccessPassword, $tableNamePrefix; if( $password != $logAccessPassword ) { echo "Incorrect password."; gs_log( "Failed show_log access with password: $password" ); } else { $query = "SELECT * FROM $tableNamePrefix"."log;"; $result = gs_queryDatabase( $query ); $numRows = mysql_numrows( $result ); echo "$numRows log entries:


\n"; for( $i=0; $i<$numRows; $i++ ) { $time = mysql_result( $result, $i, "entry_time" ); $entry = mysql_result( $result, $i, "entry" ); echo "$time:
$entry
\n"; } } } function gs_clearLog() { $password = ""; if( isset( $_REQUEST[ "password" ] ) ) { $password = $_REQUEST[ "password" ]; } global $logAccessPassword, $tableNamePrefix; if( $password != $logAccessPassword ) { echo "Incorrect password."; gs_log( "Failed clear_log access with password: $password" ); } else { $query = "DELETE FROM $tableNamePrefix"."log;"; $result = gs_queryDatabase( $query ); if( $result ) { echo "Log cleared."; } else { echo "DELETE operation failed?"; } } } function gs_getPlayerID() { // disable autocommit so that FOR UPDATE actually works gs_queryDatabase( "SET AUTOCOMMIT = 0;" ); global $tableNamePrefix; $query = "SELECT next_player_id FROM $tableNamePrefix"."server_globals ". "FOR UPDATE;"; $result = gs_queryDatabase( $query ); $numRows = mysql_numrows( $result ); // default if none in DB yet // note that lucky first player gets this ID $id_to_return = "0000000"; if( $numRows > 0 ) { // get the one from DB $id_to_return = mysql_result( $result, 0, "next_player_id" ); } else { // no rows // create one $query = "INSERT INTO $tableNamePrefix"."server_globals VALUES ( " . "'$id_to_return', CURRENT_TIMESTAMP );"; $result = gs_queryDatabase( $query ); } echo "$id_to_return"; // inser a new one by hashing this one $next_player_id = md5( $id_to_return ); $next_player_id = strtoupper( $next_player_id ); $next_player_id = substr( $next_player_id, 0, 7 ); $query = "UPDATE $tableNamePrefix"."server_globals SET " . "next_player_id = '$next_player_id';"; $result = gs_queryDatabase( $query ); gs_queryDatabase( "COMMIT;" ); gs_queryDatabase( "SET AUTOCOMMIT = 1;" ); } function gs_createForFriend() { $player_id = ""; if( isset( $_REQUEST[ "player_id" ] ) ) { $player_id = $_REQUEST[ "player_id" ]; } $player_id = strtoupper( $player_id ); gs_createGame( $player_id, 1 ); } // inPrivate is 0 or 1 function gs_createGame( $inPlayerID, $inPrivate ) { global $tableNamePrefix; $found_unused_id = 0; $salt = 0; while( ! $found_unused_id ) { $randVal = rand(); $hash = md5( $inPlayerID . uniqid( "$randVal"."$salt", true ) ); $hash = strtoupper( $hash ); $game_id = substr( $hash, 0, 7 ); // make code more human-friendly (alpha only) $digitArray = array( "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ); $letterArray = array( "W", "H", "J", "K", "X", "M", "N", "P", "T", "Y" ); $game_id = str_replace( $digitArray, $letterArray, $game_id ); $game_passcode = $hash; $player_transforms = array( array(), array() ); for( $i=0; $i<16; $i++ ) { array_push( $player_transforms[0], $i ); array_push( $player_transforms[1], $i ); } // do random swaps to make transforms for( $i=0; $i<15; $i++ ) { for( $t=0; $t<2; $t++ ) { if( $player_transforms[ $t ][ $i ] == $i ) { // not swapped yet // find an unswapped partner $indB = rand( $i+1, 15 ); while( $player_transforms[$t][ $indB ] != $indB ) { // value at indB already swapped $indB = rand( $i+1, 15 ); } $player_transforms[$t][ $i ] = $player_transforms[$t][ $indB ]; $player_transforms[$t][ $indB ] = $i; } } } $player_1_transform = implode( ",", $player_transforms[0] ); $player_2_transform = implode( ",", $player_transforms[1] ); /* "CREATE TABLE $tableName(" . "game_id CHAR(7) NOT NULL PRIMARY KEY," . "game_passcode CHAR(32) NOT NULL," . "private TINYINT NOT NULL," . "creation_date DATETIME NOT NULL," . "touch_date DATETIME NOT NULL," . "player_1_id CHAR(7) NOT NULL," . "player_2_id CHAR(7) NOT NULL," . "player_1_transform CHAR(37) NOT NULL," . "player_2_transform CHAR(37) NOT NULL," . "player_1_ready TINYINT NOT NULL," . "player_2_ready TINYINT NOT NULL," . "player_1_touch_date DATETIME NOT NULL," . "player_2_touch_date DATETIME NOT NULL," . "state_number INT NOT NULL ) ENGINE = INNODB;"; */ $query = "INSERT INTO $tableNamePrefix". "games VALUES ( " . "'$game_id', '$game_passcode', ". "'$inPrivate', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, ". "'$inPlayerID', '0000000', ". "'$player_1_transform', '$player_2_transform', '1', '0', ". "CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, '0' );"; $result = mysql_query( $query ); if( $result ) { $found_unused_id = 1; // build empty columns in table global $blockColumns; for( $c=0; $c<$blockColumns; $c++ ) { $query = "INSERT INTO $tableNamePrefix". "columns VALUES ( " . "'$game_id', '$c', '', 0 );"; gs_queryDatabase( $query ); } $gameTypeString = "Stranger"; if( $inPrivate ) { $gameTypeString = "Friend"; } gs_log( "$gameTypeString game $game_id created by ". "player $inPlayerID" ); echo "$game_id\n"; echo "$game_passcode\n"; echo "1\n"; echo "$player_1_transform"; } else { global $debug; if( $debug == 1 ) { echo "Duplicate ids? Error: " . mysql_error() ."
"; } // try again $salt += 1; } } } function gs_joinWithFriend() { $game_id = ""; if( isset( $_REQUEST[ "game_id" ] ) ) { $game_id = $_REQUEST[ "game_id" ]; } $game_id = strtoupper( $game_id ); $player_id = ""; if( isset( $_REQUEST[ "player_id" ] ) ) { $player_id = $_REQUEST[ "player_id" ]; } $player_id = strtoupper( $player_id ); global $tableNamePrefix; /* "CREATE TABLE $tableName(" . "game_id CHAR(7) NOT NULL PRIMARY KEY," . "game_passcode CHAR(32) NOT NULL," . "private TINYINT NOT NULL," . "creation_date DATETIME NOT NULL," . "touch_date DATETIME NOT NULL," . "player_1_id CHAR(7) NOT NULL," . "player_2_id CHAR(7) NOT NULL," . "player_1_transform CHAR(37) NOT NULL," . "player_2_transform CHAR(37) NOT NULL," . "player_1_ready TINYINT NOT NULL," . "player_2_ready TINYINT NOT NULL," . "player_1_touch_date DATETIME NOT NULL," . "player_2_touch_date DATETIME NOT NULL," . "state_number INT NOT NULL ) ENGINE = INNODB;"; */ $query = "SELECT * FROM $tableNamePrefix"."games ". "WHERE game_id = '$game_id' AND player_1_id != '$player_id' ". "AND player_2_ready = '0';"; $result = gs_queryDatabase( $query ); $numRows = mysql_numrows( $result ); if( $numRows == 1 ) { $row = mysql_fetch_array( $result, MYSQL_ASSOC ); $game_passcode = $row[ "game_passcode" ]; $player_2_transform = $row[ "player_2_transform" ]; $query = "UPDATE $tableNamePrefix"."games SET " . "touch_date = CURRENT_TIMESTAMP, " . "player_2_id = '$player_id', " . "player_2_ready = '1', " . "player_2_touch_date = CURRENT_TIMESTAMP " . "WHERE game_id = '$game_id' AND game_passcode = '$game_passcode';"; $result = gs_queryDatabase( $query ); gs_log( "Friend game $game_id joined by player $player_id" ); echo "$game_id\n"; echo "$game_passcode\n"; echo "2\n"; echo "$player_2_transform"; } else { gs_operationError( "Could not find joinable game matching " . $game_id ); } } function gs_joinWithStranger() { $player_id = ""; if( isset( $_REQUEST[ "player_id" ] ) ) { $player_id = $_REQUEST[ "player_id" ]; } $player_id = strtoupper( $player_id ); // first, look for non-private games that aren't full // sort by change date (prefer ones that have been checked by waiting // opponent most recently) // ignore those that haven't been checked for 20 seconds or more // (abandoned?) // disable autocommit so that FOR UPDATE actually works gs_queryDatabase( "SET AUTOCOMMIT = 0;" ); global $tableNamePrefix; $query = "SELECT * FROM $tableNamePrefix"."games ". "WHERE private = '0' AND player_2_ready = '0' ". "AND player_1_id != '$player_id' ". "AND touch_date > SUBTIME( CURRENT_TIMESTAMP, '0 0:0:20.00' ) ". "ORDER BY touch_date DESC ". "FOR UPDATE;"; $result = gs_queryDatabase( $query ); $numRows = mysql_numrows( $result ); if( $numRows > 0 ) { $row = mysql_fetch_array( $result, MYSQL_ASSOC ); $game_id = $row[ "game_id" ]; $game_passcode = $row[ "game_passcode" ]; $player_2_transform = $row[ "player_2_transform" ]; $query = "UPDATE $tableNamePrefix"."games SET " . "touch_date = CURRENT_TIMESTAMP, " . "player_2_id = '$player_id', " . "player_2_ready = '1', " . "player_2_touch_date = CURRENT_TIMESTAMP " . "WHERE game_id = '$game_id' AND game_passcode = '$game_passcode';"; $result = gs_queryDatabase( $query ); gs_log( "Stranger game $game_id joined by player $player_id" ); echo "$game_id\n"; echo "$game_passcode\n"; echo "2\n"; echo "$player_2_transform"; } else { // no empty games found // create a new public game gs_createGame( $player_id, 0 ); } gs_queryDatabase( "COMMIT;" ); gs_queryDatabase( "SET AUTOCOMMIT = 1;" ); } function gs_isPartnerReady() { $game_id = ""; if( isset( $_REQUEST[ "game_id" ] ) ) { $game_id = $_REQUEST[ "game_id" ]; } $game_passcode = ""; if( isset( $_REQUEST[ "game_passcode" ] ) ) { $game_passcode = $_REQUEST[ "game_passcode" ]; } $player_number = ""; if( isset( $_REQUEST[ "player_number" ] ) ) { $player_number = $_REQUEST[ "player_number" ]; } $game_id = strtoupper( $game_id ); $game_passcode = strtoupper( $game_passcode ); global $tableNamePrefix; /* "CREATE TABLE $tableName(" . "game_id CHAR(7) NOT NULL PRIMARY KEY," . "game_passcode CHAR(32) NOT NULL," . "private TINYINT NOT NULL," . "creation_date DATETIME NOT NULL," . "touch_date DATETIME NOT NULL," . "player_1_id CHAR(7) NOT NULL," . "player_2_id CHAR(7) NOT NULL," . "player_1_transform CHAR(37) NOT NULL," . "player_2_transform CHAR(37) NOT NULL," . "player_1_ready TINYINT NOT NULL," . "player_2_ready TINYINT NOT NULL," . "player_1_touch_date DATETIME NOT NULL," . "player_2_touch_date DATETIME NOT NULL," . "state_number INT NOT NULL ) ENGINE = INNODB;"; */ $query = "SELECT * FROM $tableNamePrefix"."games ". "WHERE game_id = '$game_id' AND game_passcode = '$game_passcode';"; $result = gs_queryDatabase( $query ); $numRows = mysql_numrows( $result ); if( $numRows == 1 ) { $row = mysql_fetch_array( $result, MYSQL_ASSOC ); $otherReady = 0; if( $player_number == 1 ) { $otherReady = $row[ "player_2_ready" ]; } else { $otherReady = $row[ "player_1_ready" ]; } echo "$otherReady"; // touched, update timestamp $query = "UPDATE $tableNamePrefix"."games SET " . "touch_date = CURRENT_TIMESTAMP " . "WHERE game_id = '$game_id' AND game_passcode = '$game_passcode';"; $result = gs_queryDatabase( $query ); } else { gs_operationError( "No game matched ID and passcode" ); } /* ?action=is_partner_ready&game_id=0a4d516&game_passcode=0a4d516e820579bb030f3eb66d0f3035&player_number=1 */ } function gs_reportAlive() { $game_id = ""; if( isset( $_REQUEST[ "game_id" ] ) ) { $game_id = $_REQUEST[ "game_id" ]; } $game_passcode = ""; if( isset( $_REQUEST[ "game_passcode" ] ) ) { $game_passcode = $_REQUEST[ "game_passcode" ]; } $player_number = ""; if( isset( $_REQUEST[ "player_number" ] ) ) { $player_number = $_REQUEST[ "player_number" ]; } $playerTouchDateName = "player_1_touch_date"; if( $player_number == "2" ) { $playerTouchDateName = "player_2_touch_date"; } global $tableNamePrefix; $query = "UPDATE $tableNamePrefix"."games SET " . "touch_date = CURRENT_TIMESTAMP, " . "$playerTouchDateName = CURRENT_TIMESTAMP " . "WHERE game_id = '$game_id' ". "AND game_passcode = '$game_passcode';"; $result = gs_queryDatabase( $query ); echo "1"; } function gs_postMove() { $game_id = ""; if( isset( $_REQUEST[ "game_id" ] ) ) { $game_id = $_REQUEST[ "game_id" ]; } $game_passcode = ""; if( isset( $_REQUEST[ "game_passcode" ] ) ) { $game_passcode = $_REQUEST[ "game_passcode" ]; } $player_number = ""; if( isset( $_REQUEST[ "player_number" ] ) ) { $player_number = $_REQUEST[ "player_number" ]; } $num_dirty_columns = ""; if( isset( $_REQUEST[ "num_dirty_columns" ] ) ) { $num_dirty_columns = $_REQUEST[ "num_dirty_columns" ]; } $game_id = strtoupper( $game_id ); $game_passcode = strtoupper( $game_passcode ); global $tableNamePrefix; /* "CREATE TABLE $tableName(" . "game_id CHAR(7) NOT NULL PRIMARY KEY," . "game_passcode CHAR(32) NOT NULL," . "private TINYINT NOT NULL," . "creation_date DATETIME NOT NULL," . "touch_date DATETIME NOT NULL," . "player_1_id CHAR(7) NOT NULL," . "player_2_id CHAR(7) NOT NULL," . "player_1_transform CHAR(37) NOT NULL," . "player_2_transform CHAR(37) NOT NULL," . "player_1_ready TINYINT NOT NULL," . "player_2_ready TINYINT NOT NULL," . "player_1_touch_date DATETIME NOT NULL," . "player_2_touch_date DATETIME NOT NULL," . "state_number INT NOT NULL ) ENGINE = INNODB;"; */ // disable autocommit so that FOR UPDATE actually works gs_queryDatabase( "SET AUTOCOMMIT = 0;" ); $query = "SELECT * FROM $tableNamePrefix"."games ". "WHERE game_id = '$game_id' AND game_passcode = '$game_passcode' ". "FOR UPDATE;"; $result = gs_queryDatabase( $query ); $numRows = mysql_numrows( $result ); if( $numRows == 1 ) { $row = mysql_fetch_array( $result, MYSQL_ASSOC ); $state_number = $row[ "state_number" ]; // new state $state_number ++; for( $c=0; $c<$num_dirty_columns; $c++ ) { $paramName = "dirty_column_$c"; $columnData = ""; if( isset( $_REQUEST[ $paramName ] ) ) { $columnData = $_REQUEST[ $paramName ]; } else { gs_operationError( "Column missing from input" ); } //echo "column data = $columnData
"; $dataParts = explode( "_", $columnData ); /* "CREATE TABLE $tableName(" . "game_id CHAR(7) NOT NULL," . "column_index TINYINT NOT NULL," . "blocks TEXT NOT NULL," . "changed_in_state INT NOT NULL, ". "PRIMARY KEY( game_id, column_index ) );"; */ $column_index = array_shift( $dataParts ); if( $player_number == 2 ) { // flip left-to-right global $blockColumns; $column_index = $blockColumns - 1 - $column_index; } $numParts = count( $dataParts ); //echo "numParts = $numParts
"; // put remaining blocks back together $blocks = implode( "_", $dataParts ); //echo "blocks = $blocks
"; $query = "UPDATE $tableNamePrefix"."columns SET " . "blocks = '$blocks', " . "changed_in_state = '$state_number' " . "WHERE game_id = '$game_id' AND ". "column_index = '$column_index';"; $result = gs_queryDatabase( $query ); } $playerTouchDateName = "player_1_touch_date"; if( $player_number == "2" ) { $playerTouchDateName = "player_2_touch_date"; } $query = "UPDATE $tableNamePrefix"."games SET " . "touch_date = CURRENT_TIMESTAMP, " . "$playerTouchDateName = CURRENT_TIMESTAMP, " . "state_number = '$state_number' " . "WHERE game_id = '$game_id' AND game_passcode = '$game_passcode';"; $result = gs_queryDatabase( $query ); echo "1"; } else { gs_operationError( "No game matched ID and passcode" ); } /* http://localhost/jcr13/game7/server.php?action=post_move&game_id=fac4e7c&game_passcode=fac4e7c03cf367f954ace1a3480966fe&player_number=1&num_dirty_columns=1&dirty_column_0=5_16A */ // unlock rows that were locked by FOR UPDATE above gs_queryDatabase( "COMMIT;" ); gs_queryDatabase( "SET AUTOCOMMIT = 1;" ); } function gs_getChangedColumns() { $game_id = ""; if( isset( $_REQUEST[ "game_id" ] ) ) { $game_id = $_REQUEST[ "game_id" ]; } $game_passcode = ""; if( isset( $_REQUEST[ "game_passcode" ] ) ) { $game_passcode = $_REQUEST[ "game_passcode" ]; } $player_number = ""; if( isset( $_REQUEST[ "player_number" ] ) ) { $player_number = $_REQUEST[ "player_number" ]; } $last_state_seen = ""; if( isset( $_REQUEST[ "last_state_seen" ] ) ) { $last_state_seen = $_REQUEST[ "last_state_seen" ]; } $game_id = strtoupper( $game_id ); $game_passcode = strtoupper( $game_passcode ); global $tableNamePrefix; /* "CREATE TABLE $tableName(" . "game_id CHAR(7) NOT NULL PRIMARY KEY," . "game_passcode CHAR(32) NOT NULL," . "private TINYINT NOT NULL," . "creation_date DATETIME NOT NULL," . "touch_date DATETIME NOT NULL," . "player_1_id CHAR(7) NOT NULL," . "player_2_id CHAR(7) NOT NULL," . "player_1_transform CHAR(37) NOT NULL," . "player_2_transform CHAR(37) NOT NULL," . "player_1_ready TINYINT NOT NULL," . "player_2_ready TINYINT NOT NULL," . "player_1_touch_date DATETIME NOT NULL," . "player_2_touch_date DATETIME NOT NULL," . "state_number INT NOT NULL ) ENGINE = INNODB;"; */ $query = "SELECT * FROM $tableNamePrefix"."games ". "WHERE game_id = '$game_id' AND game_passcode = '$game_passcode';"; $result = gs_queryDatabase( $query ); $numRows = mysql_numrows( $result ); if( $numRows == 1 ) { $row = mysql_fetch_array( $result, MYSQL_ASSOC ); $state_number = $row[ "state_number" ]; $partnerTouchDate = $row[ "player_1_touch_date" ]; if( $player_number == 1 ) { $partnerTouchDate = $row[ "player_2_touch_date" ]; } // compute seconds since partner touched $query = "SELECT TIME_TO_SEC( TIMEDIFF( CURRENT_TIMESTAMP, ". " '$partnerTouchDate' ) );"; $result = gs_queryDatabase( $query ); $secondsSincePartnerActed = mysql_result( $result, 0, 0 ); $query = "SELECT * FROM $tableNamePrefix"."columns ". "WHERE game_id = '$game_id' AND ". "changed_in_state > $last_state_seen;"; $result = gs_queryDatabase( $query ); $numChangedColumns = mysql_numrows( $result ); echo "$secondsSincePartnerActed\n"; echo "$state_number\n"; echo "$numChangedColumns\n"; for( $i=0; $i<$numChangedColumns; $i++ ) { $blocks = mysql_result( $result, $i, "blocks" ); $column_index = mysql_result( $result, $i, "column_index" ); if( $player_number == 2 ) { // flip left-to-right global $blockColumns; $column_index = $blockColumns - 1 - $column_index; } echo "$column_index" . "_" . "$blocks\n"; } $playerTouchDateName = "player_1_touch_date"; if( $player_number == "2" ) { $playerTouchDateName = "player_2_touch_date"; } $query = "UPDATE $tableNamePrefix"."games SET " . "touch_date = CURRENT_TIMESTAMP, " . "$playerTouchDateName = CURRENT_TIMESTAMP " . "WHERE game_id = '$game_id' AND game_passcode = '$game_passcode';"; gs_queryDatabase( $query ); } else { gs_operationError( "No game matched ID and passcode" ); } /* ?action=get_changed_columns&game_id=0e86e62&game_passcode=0e86e6239c67bcc56b4b6955a8fd501c&player_number=1&last_state_seen=1 */ } // check if we should flush stale games from the database // do this every 5 minutes function gs_checkForFlush() { global $tableNamePrefix; $tableName = "$tableNamePrefix"."server_globals"; if( !gs_doesTableExist( $tableName ) ) { return; } gs_queryDatabase( "SET AUTOCOMMIT = 0;" ); $query = "SELECT last_flush_time FROM $tableName ". "WHERE last_flush_time < SUBTIME( CURRENT_TIMESTAMP, '0 0:05:0.000' ) ". "FOR UPDATE;"; $result = gs_queryDatabase( $query ); if( mysql_numrows( $result ) > 0 ) { // last flush time is old global $tableNamePrefix; $gamesTable = $tableNamePrefix . "games"; $columnsTable = $tableNamePrefix . "columns"; // Games that haven't been fully joined yet // need to be checked by the creator (player 1) every 5 seconds. // If they linger 20 seconds without being checked, they are ignored // by strangers looking to join. // If they linger 40 seconds without being checked, we drop them. $query = "DELETE $gamesTable, $columnsTable ". "FROM $gamesTable JOIN $columnsTable ". "WHERE player_2_ready = '0' ". "AND $gamesTable.touch_date < ". " SUBTIME( CURRENT_TIMESTAMP, '0 0:00:40.00' ) ". "AND $gamesTable.game_id = $columnsTable.game_id;"; $result = gs_queryDatabase( $query ); $numRowsRemoved = mysql_affected_rows(); gs_log( "Flush operation on unstarted games removed $numRowsRemoved". " rows." ); // games that have been joined / started can linger for a long // time with no server action (while players are thinking, etc). // also, players can quit playing and resume playing later // (hmmm... do we want to support this?) // for now, give them 2 hours of idle time $query = "DELETE $gamesTable, $columnsTable ". "FROM $gamesTable JOIN $columnsTable ". "WHERE player_2_ready = '1' ". "AND $gamesTable.touch_date < ". " SUBTIME( CURRENT_TIMESTAMP, '0 2:00:0.00' ) ". "AND $gamesTable.game_id = $columnsTable.game_id;"; $result = gs_queryDatabase( $query ); $numRowsRemoved = mysql_affected_rows(); gs_log( "Flush operation on started games removed $numRowsRemoved". " rows." ); global $enableLog; if( $enableLog ) { // count remaining games for log $query = "SELECT COUNT(*) FROM $gamesTable;"; $result = gs_queryDatabase( $query ); $count = mysql_result( $result, 0, 0 ); gs_log( "After flush, $count games left." ); } // set new flush time $query = "UPDATE $tableName SET " . "last_flush_time = CURRENT_TIMESTAMP;"; $result = gs_queryDatabase( $query ); } gs_queryDatabase( "COMMIT;" ); gs_queryDatabase( "SET AUTOCOMMIT = 1;" ); } // general-purpose functions down here, many copied from seedBlogs /** * Connects to the database according to the database variables. */ function gs_connectToDatabase() { global $databaseServer, $databaseUsername, $databasePassword, $databaseName; mysql_connect( $databaseServer, $databaseUsername, $databasePassword ) or gs_fatalError( "Could not connect to database server: " . mysql_error() ); mysql_select_db( $databaseName ) or gs_fatalError( "Could not select $databaseName database: " . mysql_error() ); } /** * Closes the database connection. */ function gs_closeDatabase() { mysql_close(); } /** * Queries the database, and dies with an error message on failure. * * @param $inQueryString the SQL query string. * * @return a result handle that can be passed to other mysql functions. */ function gs_queryDatabase( $inQueryString ) { $result = mysql_query( $inQueryString ) or gs_fatalError( "Database query failed:
$inQueryString

" . mysql_error() ); return $result; } /** * Checks whether a table exists in the currently-connected database. * * @param $inTableName the name of the table to look for. * * @return 1 if the table exists, or 0 if not. */ function gs_doesTableExist( $inTableName ) { // check if our table exists $tableExists = 0; $query = "SHOW TABLES"; $result = gs_queryDatabase( $query ); $numRows = mysql_numrows( $result ); for( $i=0; $i<$numRows && ! $tableExists; $i++ ) { $tableName = mysql_result( $result, $i, 0 ); if( $tableName == $inTableName ) { $tableExists = 1; } } return $tableExists; } function gs_log( $message ) { global $enableLog, $tableNamePrefix; $slashedMessage = addslashes( $message ); if( $enableLog ) { $query = "INSERT INTO $tableNamePrefix"."log VALUES ( " . "'$slashedMessage', CURRENT_TIMESTAMP );"; $result = gs_queryDatabase( $query ); } } /** * Displays the error page and dies. * * @param $message the error message to display on the error page. */ function gs_fatalError( $message ) { //global $errorMessage; // set the variable that is displayed inside error.php //$errorMessage = $message; //include_once( "error.php" ); // for now, just print error message $logMessage = "Fatal error: $message"; echo( $logMessage ); gs_log( $logMessage ); die(); } /** * Displays the operation error message and dies. * * @param $message the error message to display. */ function gs_operationError( $message ) { // for now, just print error message echo( "ERROR: $message" ); die(); } /** * Recursively applies the addslashes function to arrays of arrays. * This effectively forces magic_quote escaping behavior, eliminating * a slew of possible database security issues. * * @inValue the value or array to addslashes to. * * @return the value or array with slashes added. */ function gs_addslashes_deep( $inValue ) { return ( is_array( $inValue ) ? array_map( 'gs_addslashes_deep', $inValue ) : addslashes( $inValue ) ); } /** * Recursively applies the stripslashes function to arrays of arrays. * This effectively disables magic_quote escaping behavior. * * @inValue the value or array to stripslashes from. * * @return the value or array with slashes removed. */ function gs_stripslashes_deep( $inValue ) { return ( is_array( $inValue ) ? array_map( 'sb_stripslashes_deep', $inValue ) : stripslashes( $inValue ) ); } ?> between-6+dfsg1.orig/game7/server/settings.php0000640000175000017500000000172511100426276020124 0ustar pabspabsbetween-6+dfsg1.orig/game7/server/protocol.txt0000640000175000017500000000661311101136423020147 0ustar pabspabsAll returns are whitespace-delimited. Error returns start with the string "ERROR:" === Call: server.php?action=get_player_id Returns: playerID Where: playerID = string Note: Used to prevent joining game with self. === Call: server.php?action=create_for_friend&player_id=[id string] Returns: gameID gamePasscode playerNumber playerBlockTransform Where: gameID = string gamePasscode = string playerNumber = 1 or 2 playerBlockTransform = comma-delimited list of indices 0..15 Note: must check is_partner_ready before playing. === Call: server.php?action=join_with_friend&player_id=[id string]&game_id=[id string] Returns: gameID gamePasscode playerNumber playerBlockTransform Where: gameID = string gamePasscode = string playerNumber = 1 or 2 playerBlockTransform = comma-delimited list of indices 0..15 Note: no need to check is_partner_ready before playing. === Call: server.php?action=join_with_stranger&player_id=[id string] Returns: gameID gamePasscode playerNumber playerBlockTransform Where: gameID = string gamePasscode = string playerNumber = 1 or 2 playerBlockTransform = comma-delimited list of indices 0..15 Note: must check is_partner_ready before playing. Must keep checking for available partner every 5 seconds until a partner is provided. If an unmatched gameID goes unchecked for more than 20 seconds, it is assumed abandoned and discarded from the server. === General note: player_id is not used by any of the following calls. The purpose of player_id is to ensure that players do not join games with themselves accidentally. === Call: server.php?action=is_partner_ready&game_id=[id string]&game_passcode=[passcode string]&player_number=[1 or 2] Returns: readyFlag Where: readyFlag = 0 or 1 Note: player_number in the call is *our* player number, not partner number. === Call: server.php?action=report_alive&game_id=[id string]&game_passcode=[passcode string]&player_number=[1 or 2] Returns: successFlag Where: successFlag = 1 Note: post_move and get_changed_columns also updates alive status. Thus, report_alive should only be called during periods of inactivity, at least once every 5 minutes during such periods. === Call (params probably in POST body): server.php?action=post_move&game_id=[id string]&game_passcode=[passcode string]&player_number=[1 or 2]&num_dirty_columns=[number]&dirty_column_0=[column string]&dirty_column_1=[column string]& ... &dirty_column_N=[column string] Returns: successFlag Where: successFlag = 1 Note: Each column string starts with its column index number, followed by a "_", followed by a "_"-delimited list of block color signatures. Blocks are listed starting with the block in row 0 === Call: server.php?action=get_changed_columns&game_id=[id string]&game_passcode=[passcode string]&player_number=[1 or 2]&last_state_seen=[number] Returns: secondsSincePartnerActed stateNumber numChangedColumns column0 column1 ... columnN Where: secondsSincePartnerActed = integer >= 0 stateNumber = integer >= 0 numChangedColumns = integer >=0 columnX = column string (see below) Notes: -- last_state_seen indicates the last state fetched by the client from the server. -- secondsSincePartnerActed can be used to detect a zombie partner. -- Each column string starts with its column index number, followed by a "_", followed by a "_"-delimited list of block color signatures. Blocks are listed starting with the block in row 0 between-6+dfsg1.orig/minorGems/0000750000175000017500000000000011503620617015201 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/game/0000750000175000017500000000000011435543334016116 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/game/gameGraphics.h0000640000175000017500000000226511435543334020667 0ustar pabspabs // platform-independent wrapper for graphics primitives void setDrawColor( float inR, float inG, float inB, float inA ); // defaults to non-additive blending void toggleAdditiveBlend( char inAdditive ); // draw using last set color // four vertices per quad void drawQuads( int inNumQuads, double inVertices[] ); // four r,g,b,a values per quad vertex void drawQuads( int inNumQuads, double inVertices[], float inVertexColors[] ); // draw using last set color // three vertices per triangle void drawTriangles( int inNumTriangles, double inVertices[], char inStrip=false, char inFan=false ); // four r,g,b,a values per triangle vertex void drawTrianglesColor( int inNumTriangles, double inVertices[], float inVertexColors[], char inStrip=false, char inFan=false ); // switch into stencil-buffer drawing mode // all primitives drawn add to the area that is inside the stencil void startAddingToStencil( char inDrawColorToo ); // switch into mode where further drawing operations are passed through // stenciled area void startDrawingThroughStencil(); // stop stenciling and clear stencil buffer void stopStencil(); between-6+dfsg1.orig/minorGems/game/platforms/0000750000175000017500000000000011435543334020125 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/game/platforms/openGL/0000750000175000017500000000000011435543334021311 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/game/platforms/openGL/gameGraphicsGL.cpp0000640000175000017500000000674711435543334024651 0ustar pabspabs#include "minorGems/game/gameGraphics.h" #include void setDrawColor( float inR, float inG, float inB, float inA ) { glColor4f( inR, inG, inB, inA ); } void toggleAdditiveBlend( char inAdditive ) { if( inAdditive ) { glBlendFunc( GL_SRC_ALPHA, GL_ONE ); } else { glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); } } void drawQuads( int inNumQuads, double inVertices[] ) { glEnableClientState( GL_VERTEX_ARRAY ); glVertexPointer( 2, GL_DOUBLE, 0, inVertices ); glDrawArrays( GL_QUADS, 0, inNumQuads * 4 ); glDisableClientState( GL_VERTEX_ARRAY ); } void drawQuads( int inNumQuads, double inVertices[], float inVertexColors[] ) { glEnableClientState( GL_VERTEX_ARRAY ); glVertexPointer( 2, GL_DOUBLE, 0, inVertices ); glEnableClientState( GL_COLOR_ARRAY ); glColorPointer( 4, GL_FLOAT, 0, inVertexColors ); glDrawArrays( GL_QUADS, 0, inNumQuads * 4 ); glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_COLOR_ARRAY ); } void drawTriangles( int inNumTriangles, double inVertices[], char inStrip, char inFan ) { glEnableClientState( GL_VERTEX_ARRAY ); glVertexPointer( 2, GL_DOUBLE, 0, inVertices ); if( inStrip ) { glDrawArrays( GL_TRIANGLE_STRIP, 0, inNumTriangles + 2 ); } else if( inFan ) { glDrawArrays( GL_TRIANGLE_FAN, 0, inNumTriangles + 2 ); } else { glDrawArrays( GL_TRIANGLES, 0, inNumTriangles * 3 ); } glDisableClientState( GL_VERTEX_ARRAY ); } void drawTrianglesColor( int inNumTriangles, double inVertices[], float inVertexColors[], char inStrip, char inFan ) { glEnableClientState( GL_VERTEX_ARRAY ); glVertexPointer( 2, GL_DOUBLE, 0, inVertices ); glEnableClientState( GL_COLOR_ARRAY ); glColorPointer( 4, GL_FLOAT, 0, inVertexColors ); if( inStrip ) { glDrawArrays( GL_TRIANGLE_STRIP, 0, inNumTriangles + 2 ); } else if( inFan ) { glDrawArrays( GL_TRIANGLE_FAN, 0, inNumTriangles + 2 ); } else { glDrawArrays( GL_TRIANGLES, 0, inNumTriangles * 3 ); } glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_COLOR_ARRAY ); } void startAddingToStencil( char inDrawColorToo) { if( !inDrawColorToo ) { // stop updating color glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); // skip fully-transparent areas glEnable( GL_ALPHA_TEST ); glAlphaFunc( GL_GREATER, 0 ); } // Draw 1 into the stencil buffer wherever a sprite is glEnable( GL_STENCIL_TEST ); glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE ); glStencilFunc( GL_ALWAYS, 1, 0xffffffff ); } void startDrawingThroughStencil() { // Re-enable update of color glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); glDisable( GL_ALPHA_TEST ); // Now, only render where stencil is set to 1. glStencilFunc( GL_EQUAL, 1, 0xffffffff ); // draw if == 1 glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); } void stopStencil() { // Re-enable update of color (just in case stencil drawing was not started) glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); glDisable( GL_ALPHA_TEST ); // back to unstenciled drawing glDisable( GL_STENCIL_TEST ); glClear( GL_STENCIL_BUFFER_BIT ); } between-6+dfsg1.orig/minorGems/game/platforms/SDL/0000750000175000017500000000000011435543334020547 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/game/platforms/SDL/Makefile.GnuLinux0000640000175000017500000000150211435543334023756 0ustar pabspabs# # Modification History # # 2006-June-27 Jason Rohrer # Created. Condensed from X86 and PPC makefiles in Transcend project. # # 2007-April-23 Jason Rohrer # Removed unneeded libraries. # ## # The common GnuLinux portion of Makefiles. # Should not be made manually---used by configure to build Makefiles. ## PLATFORM_COMPILE_FLAGS = -DLINUX # various GL and X windows librariesneeded for linux # also need portaudio library (which in turn needs pthreads) PLATFORM_LINK_FLAGS = -L/usr/X11R6/lib -lGL -lGLU -lX11 -lSDL -lpthread # All platforms but OSX support g++ and need no linker hacks GXX = g++ LINK_FLAGS = ## # Platform-specific minorGems file path prefixes ## PLATFORM = Linux PLATFORM_PATH = linux TIME_PLATFORM = Unix TIME_PLATFORM_PATH = unix DIRECTORY_PLATFORM = Unix DIRECTORY_PLATFORM_PATH = unix between-6+dfsg1.orig/minorGems/game/platforms/SDL/Makefile.MacOSX0000640000175000017500000000151611435543334023304 0ustar pabspabs# # Modification History # # 2006-June-27 Jason Rohrer # Created. Adapted from Transcend project. # ## # The common MacOSX portion of Makefiles. # Should not be made manually---used by configure to build Makefiles. ## # __mac__ to trigger certain mac-specific coping code # paths to GL and GLUT headers PLATFORM_COMPILE_FLAGS = -DBSD -D__mac__ -I/System/Library/Frameworks/OpenGL.framework/Headers # various frameworks to support OpenGL and SDL # static linking against zlib and libpng PLATFORM_LINK_FLAGS = -framework OpenGL -framework SDL -framework Cocoa mac/SDLMain.m # Nothing special for OS X here GXX = g++ LINK_FLAGS = ## # Platform-specific minorGems file path prefixes ## PLATFORM = Linux PLATFORM_PATH = linux TIME_PLATFORM = Unix TIME_PLATFORM_PATH = unix DIRECTORY_PLATFORM = Unix DIRECTORY_PLATFORM_PATH = unix between-6+dfsg1.orig/minorGems/game/platforms/SDL/makeFileList0000640000175000017500000000165511435543334023053 0ustar pabspabs# example file # copy this into your game project's "gameSource" folder to define these # customizable parameters APP_NAME = gameApp2 # Can change flags here # See minorGems/game/platforms/SDL/Makefile.common for flags #DEBUG_FLAG = ${DEBUG_OFF_FLAG} LAYER_SOURCE = \ game.cpp \ landscape.cpp \ seaBottom.cpp \ seaRocks.cpp \ GAME_GRAPHICS = \ NEEDED_MINOR_GEMS_OBJECTS = \ ${SCREEN_GL_SDL_O} \ ${SINGLE_TEXTURE_GL_O} \ ${TYPE_IO_O} \ ${STRING_UTILS_O} \ ${STRING_BUFFER_OUTPUT_STREAM_O} \ ${PATH_O} \ ${TIME_O} \ ${THREAD_O} \ ${MUTEX_LOCK_O} \ ${TRANSLATION_MANAGER_O} \ ${SOCKET_O} \ ${HOST_ADDRESS_O} \ ${SOCKET_CLIENT_O} \ ${SOCKET_SERVER_O} \ ${NETWORK_FUNCTION_LOCKS_O} \ ${LOOKUP_THREAD_O} \ ${WEB_REQUEST_O} \ ${SETTINGS_MANAGER_O} \ ${FINISHED_SIGNAL_THREAD_O} \ ${SHA1_O} \ ${ENCODING_UTILS_O} \ ${DIRECTORY_O} \ ${LOG_O} \ ${APP_LOG_O} \ ${FILE_LOG_O} \ ${PRINT_LOG_O} \ ${PRINT_UTILS_O} \ between-6+dfsg1.orig/minorGems/game/platforms/SDL/Makefile.all0000640000175000017500000000273411435543334022765 0ustar pabspabs# # Modification History # # 2006-June-27 Jason Rohrer # Created. Copied from Transcend. # ## # The portion of SleepIsDeath Makefiles common to all platforms. # # Should not be made manually--- # used by SleepIsDeath/configure to build Makefiles. ## # can be overridden by makeFileList APP_NAME = gameApp ROOT_PATH = ../.. include makeFileList LAYER_OBJECTS = ${LAYER_SOURCE:.cpp=.o} TEST_SOURCE = TEST_OBJECTS = ${TEST_SOURCE:.cpp=.o} # separate dependency files LAYER_DEPENDS = ${LAYER_SOURCE:.cpp=.dep} # targets all: ${APP_NAME} ${GAME_GRAPHICS} clean: rm -f ${LAYER_DEPENDS} ${LAYER_OBJECTS} ${TEST_OBJECTS} ${NEEDED_MINOR_GEMS_OBJECTS} ${APP_NAME} ${GAME_GRAPHICS} graphics: ${GAME_GRAPHICS} ${APP_NAME}: ${LAYER_OBJECTS} ${NEEDED_MINOR_GEMS_OBJECTS} ${ICON_FILE} ${EXE_LINK} -o ${APP_NAME} ${LAYER_OBJECTS} ${NEEDED_MINOR_GEMS_OBJECTS} ${ICON_FILE} ${COMMON_LIBS} ${PLATFORM_LINK_FLAGS} # add this on Unix to support JPEG video frame output # -ljpeg ${ROOT_PATH}/minorGems/graphics/converters/unix/JPEGImageConverterUnix.cpp # # Generic: # # Map all .cpp files into .dep files # # $@ represents the name.dep file # $< represents the name.cpp file # %.dep: %.cpp ${COMPILE} -MM $< >> $@ # include them all include ${LAYER_DEPENDS} # # Generic: # # Map all png files into .tga files # # $@ represents the name.tga file # $< represents the name.png file # graphics/%.tga: %.png convert $< $@ music/%.tga: %.png convert $< $@ between-6+dfsg1.orig/minorGems/game/platforms/SDL/configure0000750000175000017500000000406211435543334022460 0ustar pabspabs#!/bin/bash # call this script from inside your game's project folder # this script creates a Makefile inside your project's "gameSource" directory # # Modification History # # 2010-April-2 Andy Sommerville # Allow menu choice from argv. # "exit 1" when user chooses 'q'; terminate build. # # 2006-June-27 Jason Rohrer # Copied/modified from Transcend project. Dropped a platforms that were only # nominally supported. # if [[ "$1" < "4" ]] ; then if [[ "$1" > "0" ]] ; then platformSelection="$1" fi fi while [ -z "$platformSelection" ] do echo "select platform:" echo " 1 -- GNU/Linux" echo " 2 -- MacOSX" echo " 3 -- Win32 using MinGW" echo " q -- quit" echo "" echo -n "> " read platformSelection if [ "$platformSelection" = "q" ] then exit 1 fi # use ASCII comparison. if [[ "$platformSelection" > "3" ]] then platformSelection="" fi if [[ "$platformSelection" < "1" ]] then platformSelection="" fi done # use partial makefiles from minorGems project makefileMinorGems="../minorGems/build/Makefile.minorGems" makefileMinorGemsTargets="../minorGems/build/Makefile.minorGems_targets" platformName="Generic" platformMakefile="generic" makefilePath="../minorGems/game/platforms/SDL" commonMakefile="$makefilePath/Makefile.common" makefileAll="$makefilePath/Makefile.all" case "$platformSelection" in "1" ) platformName="GNU/Linux" platformMakefile="$makefilePath/Makefile.GnuLinux" ;; "2" ) platformName="MacOSX" platformMakefile="$makefilePath/Makefile.MacOSX" ;; "3" ) platformName="Win32 MinGW" platformMakefile="$makefilePath/Makefile.MinGW" ;; esac rm -f Makefile.temp echo "# Auto-generated by game9/configure for the $platformName platform. Do not edit manually." > Makefile.temp rm -f gameSource/Makefile cat Makefile.temp $platformMakefile $commonMakefile $makefileMinorGems $makefileAll $makefileMinorGemsTargets > gameSource/Makefile rm Makefile.temp exit between-6+dfsg1.orig/minorGems/game/platforms/SDL/Makefile.common0000640000175000017500000000242711435543334023504 0ustar pabspabs# # Modification History # # 2004-April-30 Jason Rohrer # Created. Modified from MUTE source. # # 2005-August-29 Jason Rohrer # Added optimization options. # # 2007-April-23 Jason Rohrer # Upgraded to latest minorGems dependency format. # ## # The common portion of all Makefiles. # Should not be made manually---used by configure to build Makefiles. ## EXE_LINKER = ${GXX} RANLIB = ranlib LIBRARY_LINKER = ar DEBUG_ON_FLAG = -g #-DDEBUG_MEMORY DEBUG_OFF_FLAG = DEBUG_FLAG = ${DEBUG_ON_FLAG} PROFILE_ON_FLAG = -pg -DUSE_GPROF_THREADS PROFILE_OFF_FLAG = PROFILE_FLAG = ${PROFILE_OFF_FLAG} OPTIMIZE_ON_FLAG = -O9 OPTIMIZE_OFF_FLAG = -O0 OPTIMIZE_FLAG = ${OPTIMIZE_OFF_FLAG} # common to all platforms SOCKET_UDP_PLATFORM_PATH = unix SOCKET_UDP_PLATFORM = Unix COMPILE_FLAGS = -Wall -Wwrite-strings -Wchar-subscripts -Wparentheses ${DEBUG_FLAG} ${PLATFORM_COMPILE_FLAGS} ${PROFILE_FLAG} ${OPTIMIZE_FLAG} -I${ROOT_PATH} COMMON_LIBS = COMPILE = ${GXX} ${COMPILE_FLAGS} -c EXE_LINK = ${EXE_LINKER} ${COMPILE_FLAGS} ${LINK_FLAGS} LIBRARY_LINK = ${LIBRARY_LINKER} cru # # Generic: # # Map all .cpp C++ and C files into .o object files # # $@ represents the name.o file # $< represents the name.cpp file # .cpp.o: ${COMPILE} -o $@ $< .c.o: ${COMPILE} -o $@ $< between-6+dfsg1.orig/minorGems/game/platforms/SDL/gameSDL.cpp0000640000175000017500000004027511435543334022540 0ustar pabspabs/* * Modification History * * 2008-September-11 Jason Rohrer * Created. Copied from Cultivation. */ #include #include #include #include #include // let SDL override our main function with SDLMain #include // must do this before SDL include to prevent WinMain linker errors on win32 int mainFunction( int inArgCount, char **inArgs ); int main( int inArgCount, char **inArgs ) { return mainFunction( inArgCount, inArgs ); } #include #include "minorGems/graphics/openGL/ScreenGL.h" #include "minorGems/graphics/openGL/SceneHandlerGL.h" #include "minorGems/graphics/Color.h" #include "minorGems/graphics/openGL/gui/GUIPanelGL.h" #include "minorGems/graphics/openGL/gui/GUITranslatorGL.h" #include "minorGems/graphics/openGL/gui/TextGL.h" #include "minorGems/graphics/openGL/gui/LabelGL.h" #include "minorGems/graphics/openGL/gui/TextFieldGL.h" #include "minorGems/graphics/openGL/gui/SliderGL.h" #include "minorGems/system/Time.h" #include "minorGems/system/Thread.h" #include "minorGems/io/file/File.h" #include "minorGems/network/HostAddress.h" #include "minorGems/network/upnp/portMapping.h" #include "minorGems/util/SettingsManager.h" #include "minorGems/util/TranslationManager.h" #include "minorGems/util/stringUtils.h" #include "minorGems/util/SimpleVector.h" #include "minorGems/util/log/AppLog.h" #include "minorGems/util/log/FileLog.h" #include "minorGems/game/game.h" // some settings // size of game image int gameWidth = 320; int gameHeight = 240; // size of screen for fullscreen mode int screenWidth = 640; int screenHeight = 480; char hardToQuitMode = false; // ^ and & keys to slow down and speed up for testing char enableSlowdownKeys = false; //char enableSlowdownKeys = true; class GameSceneHandler : public SceneHandlerGL, public MouseHandlerGL, public KeyboardHandlerGL, public RedrawListenerGL, public ActionListener { public: /** * Constructs a sceen handler. * * @param inScreen the screen to interact with. * Must be destroyed by caller after this class is destroyed. */ GameSceneHandler( ScreenGL *inScreen ); virtual ~GameSceneHandler(); /** * Executes necessary init code that reads from files. * * Must be called before using a newly-constructed GameSceneHandler. * * This call assumes that the needed files are in the current working * directory. */ void initFromFiles(); ScreenGL *mScreen; // implements the SceneHandlerGL interface virtual void drawScene(); // implements the MouseHandlerGL interface virtual void mouseMoved( int inX, int inY ); virtual void mouseDragged( int inX, int inY ); virtual void mousePressed( int inX, int inY ); virtual void mouseReleased( int inX, int inY ); // implements the KeyboardHandlerGL interface virtual char isFocused() { // always focused return true; } virtual void keyPressed( unsigned char inKey, int inX, int inY ); virtual void specialKeyPressed( int inKey, int inX, int inY ); virtual void keyReleased( unsigned char inKey, int inX, int inY ); virtual void specialKeyReleased( int inKey, int inX, int inY ); // implements the RedrawListener interface virtual void fireRedraw(); // implements the ActionListener interface virtual void actionPerformed( GUIComponent *inTarget ); protected: // the time that the last frame was drawn unsigned long mLastFrameSeconds; unsigned long mLastFrameMilliseconds; // our current frame rate unsigned long mFrameMillisecondDelta; int mStartTimeSeconds; char mPaused; double mMaxFrameRate; char mPrintFrameRate; unsigned long mNumFrames; unsigned long mFrameBatchSize; unsigned long mFrameBatchStartTimeSeconds; unsigned long mFrameBatchStartTimeMilliseconds; Color mBackgroundColor; }; GameSceneHandler *sceneHandler; ScreenGL *screen; // how many pixels wide is each game pixel drawn as? int pixelZoomFactor; // function that destroys object when exit is called. // exit is the only way to stop the loop in ScreenGL void cleanUpAtExit() { AppLog::info( "exiting\n" ); delete sceneHandler; delete screen; freeFrameDrawer(); SDL_Quit(); } int mainFunction( int inNumArgs, char **inArgs ) { // check result below, after opening log, so we can log failure int sdlResult = SDL_Init( SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE ); // do this mac check after initing SDL, // since it causes various Mac frameworks to be loaded (which can // change the current working directory out from under us) #ifdef __mac__ // make sure working directory is the same as the directory // that the app resides in // this is especially important on the mac platform, which // doesn't set a proper working directory for double-clicked // app bundles // arg 0 is the path to the app executable char *appDirectoryPath = stringDuplicate( inArgs[0] ); char *appNamePointer = strstr( appDirectoryPath, "GameApp.app" ); if( appNamePointer != NULL ) { // terminate full app path to get parent directory appNamePointer[0] = '\0'; chdir( appDirectoryPath ); } delete [] appDirectoryPath; #endif AppLog::setLog( new FileLog( "log.txt" ) ); AppLog::setLoggingLevel( Log::DETAIL_LEVEL ); AppLog::info( "New game starting up" ); if( sdlResult < 0 ) { AppLog::getLog()->logPrintf( Log::CRITICAL_ERROR_LEVEL, "Couldn't initialize SDL: %s\n", SDL_GetError() ); return 0; } // read screen size from settings char widthFound = false; int readWidth = SettingsManager::getIntSetting( "screenWidth", &widthFound ); char heightFound = false; int readHeight = SettingsManager::getIntSetting( "screenHeight", &heightFound ); if( widthFound && heightFound ) { // override hard-coded defaults screenWidth = readWidth; screenHeight = readHeight; } AppLog::getLog()->logPrintf( Log::INFO_LEVEL, "Screen dimensions for fullscreen mode: %dx%d\n", screenWidth, screenHeight ); char fullscreenFound = false; int readFullscreen = SettingsManager::getIntSetting( "fullscreen", &fullscreenFound ); char fullscreen = true; if( readFullscreen == 0 ) { fullscreen = false; } screen = new ScreenGL( screenWidth, screenHeight, fullscreen, "SleepIsDeath", NULL, NULL, NULL ); // may change if specified resolution is not supported screenWidth = screen->getWidth(); screenHeight = screen->getHeight(); /* SDL_EnableKeyRepeat( SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL ); */ pixelZoomFactor = screenWidth / gameWidth; if( pixelZoomFactor * gameHeight > screenHeight ) { // screen too short pixelZoomFactor = screenHeight / gameHeight; } screen->setImageSize( pixelZoomFactor * gameWidth, pixelZoomFactor * gameHeight ); //SDL_ShowCursor( SDL_DISABLE ); sceneHandler = new GameSceneHandler( screen ); // also do file-dependent part of init for GameSceneHandler here // actually, constructor is file dependent anyway. sceneHandler->initFromFiles(); // hard to quit mode? char hardToQuitFound = false; int readHardToQuit = SettingsManager::getIntSetting( "hardToQuitMode", &hardToQuitFound ); if( readHardToQuit == 1 ) { hardToQuitMode = true; } // register cleanup function, since screen->start() will never return atexit( cleanUpAtExit ); screen->switchTo2DMode(); //glLineWidth( pixelZoomFactor ); initFrameDrawer( screenWidth, screenHeight ); screen->start(); return 0; } GameSceneHandler::GameSceneHandler( ScreenGL *inScreen ) : mScreen( inScreen ), mFrameMillisecondDelta( 0 ), mStartTimeSeconds( time( NULL ) ), mPaused( false ), mMaxFrameRate( 30 ), mPrintFrameRate( false ), mNumFrames( 0 ), mFrameBatchSize( 100 ), mFrameBatchStartTimeSeconds( time( NULL ) ), mFrameBatchStartTimeMilliseconds( 0 ), mBackgroundColor( 0, 0, 0.5, 1 ) { glClearColor( mBackgroundColor.r, mBackgroundColor.g, mBackgroundColor.b, mBackgroundColor.a ); // set external pointer so it can be used in calls below sceneHandler = this; mScreen->addMouseHandler( this ); mScreen->addKeyboardHandler( this ); mScreen->addSceneHandler( this ); mScreen->addRedrawListener( this ); Time::getCurrentTime( &mLastFrameSeconds, &mLastFrameMilliseconds ); } GameSceneHandler::~GameSceneHandler() { mScreen->removeMouseHandler( this ); mScreen->removeSceneHandler( this ); mScreen->removeRedrawListener( this ); } void GameSceneHandler::initFromFiles() { } static float viewCenterX = 0; static float viewCenterY = 0; // default -1 to +1 static float viewSize = 2; void setViewCenterPosition( float inX, float inY ) { viewCenterX = inX; viewCenterY = inY; } void setViewSize( float inSize ) { viewSize = inSize; } void GameSceneHandler::drawScene() { /* glClearColor( mBackgroundColor->r, mBackgroundColor->g, mBackgroundColor->b, mBackgroundColor->a ); */ // viewport square centered on screen (even if screen is rectangle) float hRadius = viewSize / 2; glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho( viewCenterX - hRadius, viewCenterX + hRadius, viewCenterY - hRadius, viewCenterY + hRadius, -1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); glDisable( GL_TEXTURE_2D ); glDisable( GL_CULL_FACE ); glDisable( GL_DEPTH_TEST ); drawFrame(); } static void screenToWorld( int inX, int inY, float *outX, float *outY ) { } void GameSceneHandler::mouseMoved( int inX, int inY ) { float x, y; screenToWorld( inX, inY, &x, &y ); pointerMove( x, y ); } void GameSceneHandler::mouseDragged( int inX, int inY ) { float x, y; screenToWorld( inX, inY, &x, &y ); pointerDrag( x, y ); } void GameSceneHandler::mousePressed( int inX, int inY ) { float x, y; screenToWorld( inX, inY, &x, &y ); pointerDown( x, y ); } void GameSceneHandler::mouseReleased( int inX, int inY ) { float x, y; screenToWorld( inX, inY, &x, &y ); pointerUp( x, y ); } void GameSceneHandler::fireRedraw() { if( mPaused ) { // ignore redraw event // sleep to avoid wasting CPU cycles Thread::staticSleep( 1000 ); // also ignore time that passes while paused Time::getCurrentTime( &mLastFrameSeconds, &mLastFrameMilliseconds ); return; } // deal with frame timing issues unsigned long lastMillisecondDelta = mFrameMillisecondDelta; // how many milliseconds have passed since the last frame mFrameMillisecondDelta = Time::getMillisecondsSince( mLastFrameSeconds, mLastFrameMilliseconds ); // lock down to mMaxFrameRate frames per second unsigned long minFrameTime = (unsigned long)( 1000 / mMaxFrameRate ); if( mFrameMillisecondDelta < minFrameTime ) { unsigned long timeToSleep = minFrameTime - mFrameMillisecondDelta; Thread::staticSleep( timeToSleep ); // get new frame second delta, including sleep time mFrameMillisecondDelta = Time::getMillisecondsSince( mLastFrameSeconds, mLastFrameMilliseconds ); } // avoid huge position "jumps" if we have a very large delay during a frame // (possibly caused by something going on in the background) // This will favor a slight visual slow down, but this is better than // a disorienting jump // skip this check if we are just starting up if( lastMillisecondDelta != 0 ) { if( mFrameMillisecondDelta > 6 * lastMillisecondDelta ) { // limit: this frame represents at most twice the jump of the last // frame // printf( "Limiting time jump (requested=%lu ms, last=%lu ms)\n", // mFrameMillisecondDelta, lastMillisecondDelta ); if( mFrameMillisecondDelta > 10000 ) { AppLog::warning( "Time between frames more than 10 seconds:\n" ); // way too big... investigate AppLog::getLog()->logPrintf( Log::WARNING_LEVEL, "Last time = %lu s, %lu ms\n", mLastFrameSeconds, mLastFrameMilliseconds ); Time::getCurrentTime( &mLastFrameSeconds, &mLastFrameMilliseconds ); AppLog::getLog()->logPrintf( Log::WARNING_LEVEL, "current time = %lu s, %lu ms\n", mLastFrameSeconds, mLastFrameMilliseconds ); } mFrameMillisecondDelta = 2 * lastMillisecondDelta; } } // record the time that this frame was drawn Time::getCurrentTime( &mLastFrameSeconds, &mLastFrameMilliseconds ); // for use with non-constant time-per-frame // this game is constant time-per-frame // double frameSecondsDelta = (double)mFrameMillisecondDelta / 1000.0; mNumFrames ++; if( mPrintFrameRate ) { if( mNumFrames % mFrameBatchSize == 0 ) { // finished a batch unsigned long timeDelta = Time::getMillisecondsSince( mFrameBatchStartTimeSeconds, mFrameBatchStartTimeMilliseconds ); double frameRate = 1000 * (double)mFrameBatchSize / (double)timeDelta; //AppLog::getLog()->logPrintf( // Log::DETAIL_LEVEL, printf( "Frame rate = %f frames/second\n", frameRate ); mFrameBatchStartTimeSeconds = mLastFrameSeconds; mFrameBatchStartTimeMilliseconds = mLastFrameMilliseconds; } } } static unsigned char lastKeyPressed = '\0'; void GameSceneHandler::keyPressed( unsigned char inKey, int inX, int inY ) { if( enableSlowdownKeys ) { if( inKey == '^' ) { // slow mMaxFrameRate = 2; } if( inKey == '&' ) { // normal mMaxFrameRate = 30; } } if( !hardToQuitMode ) { // q or escape if( inKey == 'q' || inKey == 'Q' || inKey == 27 ) { exit( 0 ); } } else { // # followed by ESC if( lastKeyPressed == '#' && inKey == 27 ) { exit( 0 ); } lastKeyPressed = inKey; } keyDown( inKey ); } void GameSceneHandler::keyReleased( unsigned char inKey, int inX, int inY ) { keyUp( inKey ); } void GameSceneHandler::specialKeyPressed( int inKey, int inX, int inY ) { specialKeyDown( inKey ); } void GameSceneHandler::specialKeyReleased( int inKey, int inX, int inY ) { specialKeyUp( inKey ); } void GameSceneHandler::actionPerformed( GUIComponent *inTarget ) { } between-6+dfsg1.orig/minorGems/game/platforms/SDL/Makefile.MinGW0000640000175000017500000000224411435543334023172 0ustar pabspabs# # Modification History # # 2003-November-2 Jason Rohrer # Created. # # 2003-November-10 Jason Rohrer # Removed pthread flag. # Changed LINUX flag to WIN_32 flag. # Added wsock32 library flag. # ## # The common MinGW (GNU for Win32) portion of Makefiles. # Should not be made manually---used by configure to build Makefiles. ## # static lib flag needed to link compiled objs against miniupnp PLATFORM_COMPILE_FLAGS = -DWIN_32 -DSTATICLIB # need various GL libraries, winmm, and portaudio # -mwindows tells mingw to hide the dos command window on launch PLATFORM_LINK_FLAGS = -lopengl32 -lglu32 -lmingw32 -lSDLmain -lSDL -mwindows -lwsock32 # All platforms but OSX support g++ and need no linker hacks GXX = g++ LINK_FLAGS = # don't build icon.o when make invoked with no arguments! all: SleepIsDeath icon.o: ../build/win32/icon.ico ../build/win32/icon.rc cp ../build/win32/icon.ico ../build/win32/icon.rc . windres -i icon.rc -o icon.o ICON_FILE = icon.o ## # Platform-specific minorGems file path prefixes ## PLATFORM = Win32 PLATFORM_PATH = win32 TIME_PLATFORM = Win32 TIME_PLATFORM_PATH = win32 DIRECTORY_PLATFORM = Win32 DIRECTORY_PLATFORM_PATH = win32 between-6+dfsg1.orig/minorGems/game/game.h0000640000175000017500000000424011435543334017201 0ustar pabspabs // interface between a platform-independent game engine // and the underlying platform // these are called by SDL or iPhone (or other platform) app wrapper void initFrameDrawer( int inWidth, int inHeight ); // called at application termination // good time to save state for next launch void freeFrameDrawer(); // draw scene into frame using GL function calls void drawFrame(); // these are all in world coordinates based on what is set // in setViewCenterPosition and setViewSize below // pointer movement unpressed void pointerMove( float inX, float inY ); // start of pointer press void pointerDown( float inX, float inY ); // movement with pointer pressed void pointerDrag( float inX, float inY ); // end of pointer press void pointerUp( float inX, float inY ); void keyDown( unsigned char inASCII ); void keyUp( unsigned char inASCII ); // this GL file is actually platform-independent and has nothing to do // with OpenGL // Defines key codes #include "minorGems/graphics/openGL/KeyboardHandlerGL.h" void specialKeyDown( int inKeyCode ); void specialKeyUp( int inKeyCode ); #include typedef int16_t Sint16; typedef uint8_t Uint8; // should sound be initialized? char getUsesSound(); // sample rate shared by game engine and sound rendering platform //#define gameSoundSampleRate 22050 //#define gameSoundSampleRate 44100 // #define gameSoundSampleRate 11025 // called by rendering platform when setting sample rate int getSampleRate(); // gets the next buffer-full of sound samples from the game engine // inBuffer should be filled with stereo Sint16 samples, little endian, // left-right left-right .... // NOTE: may not be called by the same thread that calls drawFrame, // depending on platform implementation void getSoundSamples( Uint8 *inBuffer, int inLengthToFillInBytes ); // These are called BY game engine (implemented by supporting platform) // true to start or resume playing // false to pause void setSoundPlaying( char inPlaying ); // for moving view around void setViewCenterPosition( float inX, float inY ); // 1:1 aspect ratio (truncated on shorter screen dimension) void setViewSize( float inSize ); between-6+dfsg1.orig/minorGems/network/0000750000175000017500000000000011435543354016700 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/network/HostAddress.h0000640000175000017500000002204711435543335021301 0ustar pabspabs/* * Modification History * * 2001-January-10 Jason Rohrer * Created. * * 2001-December-12 Jason Rohrer * Made serializable. * Changed the constructor signature. * * 2001-December-14 Jason Rohrer * Added a method for getting the local address. * Fixed several typos. * Added functions for testing equality and making copies. * Fixed a comment. * * 2002-February-25 Jason Rohrer * Made destructor virtual. * * 2002-March-25 Jason Rohrer * Added function for conversion to numerical addresses. * Changed equality function to resolve both addresses to * their numerical form first. * Changed equality function to be localhost savvy. * * 2002-March-26 Jason Rohrer * Added some print statements for testing. * Removed testing print statements. * * 2002-March-29 Jason Rohrer * Added Fortify inclusion. * * 2002-April-8 Jason Rohrer * Added an isNumerical function because hostname lookups on * numerical addresses are slow on Win32. * * 2002-April-11 Jason Rohrer * Fixed a bug in equals when both lookups fail. * * 2002-July-23 Jason Rohrer * Fixed a bug in equals when our local lookup fails. * * 2010-February-1 Jason Rohrer * Fixed a bug in getNumericalLocalAddress when our local lookup fails. */ #include "minorGems/common.h" #ifndef HOST_ADDRESS_CLASS_INCLUDED #define HOST_ADDRESS_CLASS_INCLUDED #include #include #include "minorGems/io/Serializable.h" #include "minorGems/util/stringUtils.h" #ifdef FORTIFY #include "minorGems/util/development/fortify/fortify.h" #endif /** * Address of a network host. * * @author Jason Rohrer */ class HostAddress : public Serializable { public: /** * Constructs an uninitialized address. * * Note that all other functions (besides deserialize and the * destructor) assume that the HostAddress is initialized. * * Useful prior to deserialization. */ HostAddress(); /** * Constructs an address. * * @param inAddressString a \0-terminated string containing the * host address. This string will be destroyed when this class * is destroyed, so it cannot be const. * @param inPort the port of the host. */ HostAddress( char *inAddressString, int inPort ); virtual ~HostAddress(); /** * Gets the address of the local host. * * @return the address of the local host. * Note that the mPort field in the returned HostAddress is * set to 0. * Must be destroyed by caller. */ static HostAddress *getLocalAddress(); /** * Gets the address of the local host in numerical format. * * @return the address of the local host. * Note that the mPort field in the returned HostAddress is * set to 0. * Must be destroyed by caller. */ static HostAddress *getNumericalLocalAddress(); /** * Gets a numerical version of this host address. * * For example, if we are using IPv4, this will generate a * HostAddress containing an aaa.bbb.ccc.ddd style address. * * @return a numerical version of this address, or NULL * if address resolution fails. * Must be destroyed by caller if non-NULL. */ HostAddress *getNumericalAddress(); /** * Gets whether this address is in numerical format. * For IpV4, this is xxx.xxx.xxx.xxx * * @return true if this address is numerical. */ char isNumerical(); /** * Gets whether another address is equivalent to this address. * * @param inAddress the address to compare to this address. * * @return true iff inAddress is equivalent to this address. */ char equals( HostAddress *inAddress ); /** * Makes a copy of this host address. * * @return the copy of this address. */ HostAddress *copy(); /** * Prints this address to standard out. */ void print(); // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); char *mAddressString; int mAddressLength; int mPort; }; inline HostAddress::HostAddress( char *inAddressString, int inPort ) : mAddressString( inAddressString ), mPort( inPort ) { mAddressLength = strlen( mAddressString ); } inline HostAddress::HostAddress() : mAddressString( NULL ) { mAddressLength = 0; mPort = 0; } inline HostAddress::~HostAddress() { if( mAddressString != NULL ) { delete [] mAddressString; } } inline HostAddress *HostAddress::getNumericalLocalAddress() { HostAddress *address = getLocalAddress(); if( address != NULL ) { HostAddress *numAddress = address->getNumericalAddress(); delete address; return numAddress; } return NULL; } inline char HostAddress::equals( HostAddress *inAddress ) { // if the port numbers are not equal, we can return // right away if( mPort != inAddress->mPort ) { return false; } // otherwise, the port numbers are equal, // so we need to compare the addresses // first, try to compare numercally looked-up addresses HostAddress *numericalThis = this->getNumericalAddress(); if( numericalThis != NULL ) { HostAddress *numericalOther = inAddress->getNumericalAddress(); if( numericalOther != NULL ) { char returnVal = false; // watch out for localhost loopbacks if( !strcmp( numericalThis->mAddressString, "127.0.0.1" ) ) { // this address is localhost // make sure other address is not our external local address HostAddress *localAddress = getNumericalLocalAddress(); if( localAddress != NULL ) { if( !strcmp( localAddress->mAddressString, numericalOther->mAddressString ) ) { returnVal = true; } delete localAddress; } else { // numerical lookup failed for one but not the // other, so assume addresses are different returnVal = false; } } else if( !strcmp( numericalOther->mAddressString, "127.0.0.1" ) ) { // other address is localhost // make sure this address is not our external local address HostAddress *localAddress = getNumericalLocalAddress(); if( localAddress != NULL ) { if( !strcmp( localAddress->mAddressString, numericalThis->mAddressString ) ) { returnVal = true; } delete localAddress; } else { // numerical lookup failed for one but not the // other, so assume addresses are different returnVal = false; } } // if numerical addresses are identical, // then hosts are equal if( !strcmp( numericalThis->mAddressString, numericalOther->mAddressString ) ) { returnVal = true; } delete numericalOther; delete numericalThis; return returnVal; } delete numericalThis; } // otherwise, if lookup fails, compare raw adddresses if( !strcmp( inAddress->mAddressString, mAddressString ) ) { return true; } else { return false; } } inline HostAddress *HostAddress::copy() { char *stringCopy = new char[ strlen( mAddressString ) + 1 ]; strcpy( stringCopy, mAddressString ); return new HostAddress( stringCopy, mPort ); } inline void HostAddress::print() { printf( "%s:%d", mAddressString, mPort ); } inline int HostAddress::serialize( OutputStream *inOutputStream ) { int numTransmitted = 0; numTransmitted += inOutputStream->writeLong( (long)mAddressLength ); numTransmitted +=inOutputStream->write( (unsigned char *)mAddressString, mAddressLength ); numTransmitted += inOutputStream->writeLong( (long)mPort ); return numTransmitted; } inline int HostAddress::deserialize( InputStream *inInputStream ) { int numTransmitted = 0; long readLong; numTransmitted += inInputStream->readLong( &readLong ); mAddressLength = (int)readLong; if( mAddressString != NULL ) { delete [] mAddressString; } mAddressString = new char[ mAddressLength ]; numTransmitted +=inInputStream->read( (unsigned char *)mAddressString, mAddressLength ); numTransmitted += inInputStream->readLong( &readLong ); mPort = readLong; return numTransmitted; } #endif between-6+dfsg1.orig/minorGems/network/unix/0000750000175000017500000000000011435543336017663 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/network/unix/SocketUDPUnix.cpp0000640000175000017500000001453711435543336023047 0ustar pabspabs/* * Modification History * * 2004-November-3 Jason Rohrer * Created. * * 2004-November-4 Jason Rohrer * Added code for win32 compatibility. * Fixed a memcpy bug. * * 2004-December-7 Jason Rohrer * Fixed a bug in the evaluation of wait return codes. */ /* * The following changes were needed for win32 compatibility: * -- Winsock.h included * -- socklen_t defined * -- closesocket instead of close * -- inet_aton does not exist on win32 (switched to the linux-obsolete * inet_addr) */ #include "minorGems/network/SocketUDP.h" #include "minorGems/network/NetworkFunctionLocks.h" #include "minorGems/util/stringUtils.h" #ifndef WIN_32 // standard unix includes #include #include #include #include #include #include #include #else // special includes for win32 #include // windows does not define socklen_t typedef int socklen_t; // windows does not have a close function for sockets #define close( inSocketID ) closesocket( inSocketID ) #endif #ifdef BSD // BSD does not define socklen_t typedef int socklen_t; #endif // prototypes /** * Waits on a socket for incoming data. * * @param inSocketID the socket to watch. * @param inMilliseconds the timeout. * * @return 1 if data is ready to be read with recvfrom, -2 if we * timeout, and -1 on an error. */ int waitForIncomingData( int inSocketID, long inMilliseconds ); SocketUDP::SocketUDP( unsigned short inReceivePort ) { int socketID; socketID = socket( AF_INET, SOCK_DGRAM, 0 ); // bind to receivePort struct sockaddr_in bindAddress; bindAddress.sin_family = AF_INET; bindAddress.sin_port = htons( inReceivePort ); bindAddress.sin_addr.s_addr = INADDR_ANY; bind( socketID, (struct sockaddr *)&bindAddress, sizeof(bindAddress) ); int *socketIDArray = new int[1]; socketIDArray[0] = socketID; mNativeObjectPointer = (void *)socketIDArray; } SocketUDP::~SocketUDP() { // unwrap our native object int *socketIDArray = (int *)( mNativeObjectPointer ); int socketID = socketIDArray[0]; close( socketID ); delete [] socketIDArray; } struct UDPAddress *SocketUDP::makeAddress( const char *inAddress, unsigned short inPort ) { // try converting it from aaa.bbb.ccc.ddd int convertedAddress = inet_addr( inAddress ); if( convertedAddress != -1 ) { struct UDPAddress *address = new struct UDPAddress; address->mIPAddress = convertedAddress; address->mPort = htons( inPort ); return address; } else { return NULL; } } char *SocketUDP::extractAddress( struct UDPAddress *inAddress, unsigned short *outPort ) { struct in_addr addressStructure; addressStructure.s_addr = inAddress->mIPAddress; NetworkFunctionLocks::mInet_ntoaLock.lock(); // returned string is statically allocated, copy it char *addressString = stringDuplicate( inet_ntoa( addressStructure) ); NetworkFunctionLocks::mInet_ntoaLock.unlock(); *outPort = ntohs( inAddress->mPort ); return addressString; } int SocketUDP::send( struct UDPAddress *inAddress, unsigned char *inData, unsigned long inNumBytes ) { // unwrap our native object int *socketIDArray = (int *)( mNativeObjectPointer ); int socketID = socketIDArray[0]; // pack our address into the required structure struct sockaddr_in toAddress; toAddress.sin_family = AF_INET; toAddress.sin_port = inAddress->mPort; toAddress.sin_addr.s_addr = inAddress->mIPAddress; return sendto( socketID, (char *)inData, inNumBytes, 0, (struct sockaddr *)( &toAddress ), sizeof( toAddress ) ); } int SocketUDP::receive( struct UDPAddress **outAddress, unsigned char **outData, long inTimeout ) { // unwrap our native object int *socketIDArray = (int *)( mNativeObjectPointer ); int socketID = socketIDArray[0]; if( inTimeout != -1 ) { int waitValue = waitForIncomingData( socketID, inTimeout ); // timed out or saw an error while waiting if( waitValue == -1 || waitValue == -2 ) { *outAddress = NULL; *outData = NULL; return waitValue; } // else we have data waiting } struct sockaddr_in fromAddress; int bufferSize = 10000; unsigned char *receiveBuffer = new unsigned char[ bufferSize ]; socklen_t fromAddressLength = sizeof( fromAddress ); int numReceived; numReceived = recvfrom( socketID, (char *)receiveBuffer, bufferSize, 0, (struct sockaddr *)( &fromAddress ), &fromAddressLength ); // if no error and no overflow if( numReceived >=0 && numReceived <= bufferSize ) { *outAddress = new struct UDPAddress; (*outAddress)->mPort = fromAddress.sin_port; (*outAddress)->mIPAddress = fromAddress.sin_addr.s_addr; *outData = new unsigned char[ numReceived ]; memcpy( (void *)( *outData ), (void *)receiveBuffer, numReceived ); } else { *outAddress = NULL; *outData = NULL; } delete [] receiveBuffer; return numReceived; } /* socket timing code adapted from gnut, by Josh Pieper */ /* Josh Pieper, (c) 2000 */ /* This file is distributed under the GPL, see file COPYING for details */ int waitForIncomingData( int inSocketID, long inMilliseconds ) { fd_set fsr; struct timeval tv; int returnValue; FD_ZERO( &fsr ); FD_SET( inSocketID, &fsr ); tv.tv_sec = inMilliseconds / 1000; int remainder = inMilliseconds % 1000; tv.tv_usec = remainder * 1000; returnValue = select( inSocketID + 1, &fsr, NULL, NULL, &tv ); if( returnValue == 0 ) { return -2; } else if( returnValue == -1 ) { printf( "Selecting socket during receive failed.\n" ); return returnValue; } else { return returnValue; } } between-6+dfsg1.orig/minorGems/network/web/0000750000175000017500000000000011435543336017455 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/network/web/WebClient.h0000640000175000017500000001731311435543336021510 0ustar pabspabs/* * Modification History * * 2002-May-5 Jason Rohrer * Created. * Added a utility function for receiving data. * * 2002-May-12 Jason Rohrer * Added support for fetching the final (after redirects) URL. * * 2002-May-26 Jason Rohrer * Added support for fetching mime types and content length. * Added a function for fetching MIME types alone. * * 2006-January-22 Jason Rohrer * Added support for timeouts. * * 2008-September-25 Jason Rohrer * Added POST. */ #include "minorGems/common.h" #ifndef WEB_CLIENT_INCLUDED #define WEB_CLIENT_INCLUDED #include "minorGems/network/HostAddress.h" #include "minorGems/network/Socket.h" #include "minorGems/network/SocketClient.h" #include "minorGems/network/SocketStream.h" #include #include /** * A class that implements a basic web client. * * @author Jason Rohrer. */ class WebClient { public: /** * Gets a web page. * * @param inURL the URL to get as a \0-terminated string. * Must be destroyed by caller if non-const. * @param outContentLength pointer to where the length of the content, * in bytes, should be returned. * Useful for binary content which cannot be reliably terminated * by \0. * @param outFinalURL pointer to where the actual * URL of the content (after following redirects) should be returned, * or NULL to ignore the final URL. Defaults to NULL. * The string returned in this location must be destroyed * by caller. * @param outMimeType pointer to where the MIME type * of the content should be returned, * or NULL to ignore the MIME type. Defaults to NULL. * The string returned in this location must be destroyed * by caller. * @param inTimeoutInMilliseconds the timeout value when making * the connection and again when reading data in milliseconds, * or -1 for no timeout. * Defaults to -1. * * @return the fetched web page as a \0-terminated string, * or NULL if fetching the page fails. * Must be destroyed by caller if non-NULL. */ static char *getWebPage( char *inURL, int *outContentLength, char **outFinalURL = NULL, char **outMimeType = NULL, long inTimeoutInMilliseconds = -1 ); /** * Fetches a web page via POST. * * @param inURL the URL to post to as a \0-terminated string. * Must be destroyed by caller if non-const. * @param inPostBody the body of the post as \0-terminated string. * Body must match MIME type application/x-www-form-urlencoded * Must be destroyed by caller if non-const. * @param outContentLength pointer to where the length of the content, * in bytes, should be returned. * Useful for binary content which cannot be reliably terminated * by \0. * @param outFinalURL pointer to where the actual * URL of the content (after following redirects) should be returned, * or NULL to ignore the final URL. Defaults to NULL. * The string returned in this location must be destroyed * by caller. * @param outMimeType pointer to where the MIME type * of the content should be returned, * or NULL to ignore the MIME type. Defaults to NULL. * The string returned in this location must be destroyed * by caller. * @param inTimeoutInMilliseconds the timeout value when making * the connection and again when reading data in milliseconds, * or -1 for no timeout. * Defaults to -1. * * @return the fetched web page as a \0-terminated string, * or NULL if fetching the page fails. * Must be destroyed by caller if non-NULL. */ static char *getWebPagePOST( char *inURL, char *inPostBody, int *outContentLength, char **outFinalURL = NULL, char **outMimeType = NULL, long inTimeoutInMilliseconds = -1 ); /** * Gets the MIME type for a web page without fetching the content. * * @param inURL the URL to get as a \0-terminated string. * Must be destroyed by caller if non-const. * * @return the fetched MIME type as a \0-terminated string, * or NULL if fetching the page fails. * Must be destroyed by caller if non-NULL. */ static char *getMimeType( char *inURL ); protected: /** * Receives data on a connection until the connection is closed. * * @param inSocketStream the stream to read from. * Must be destroyed by caller. * @param outContentLength pointer to where the length of the content, * in bytes, should be returned. * Useful for binary content which cannot be reliably terminated * by \0. * * @return the received data as a \0-terminated string. * Must be destroyed by caller. */ static char *receiveData( SocketStream *inSocketStream, int *outContentLength ); /** * Executes a web method. * * @param inMethod the method to execute (for example, GET or HEAD). * Must be destroyed by caller if non-const. * @param inURL the URL to get as a \0-terminated string. * Must be destroyed by caller if non-const. * @param inBody the request body as a \0-terminated string, or NULL * for bodyless requests (like GET or HEAD). * Body must match MIME type application/x-www-form-urlencoded * Must be destroyed by caller if non-const and not NULL. * @param outContentLength pointer to where the length of the content, * in bytes, should be returned. * Useful for binary content which cannot be reliably terminated * by \0. * @param outFinalURL pointer to where the actual * URL of the content (after following redirects) should be returned, * or NULL to ignore the final URL. Defaults to NULL. * The string returned in this location must be destroyed * by caller. * @param outMimeType pointer to where the MIME type * of the content should be returned, * or NULL to ignore the MIME type. Defaults to NULL. * The string returned in this location must be destroyed * by caller. * @param inTimeoutInMilliseconds the timeout value when making * the connection and again when reading data in milliseconds, * or -1 for no timeout. * Defaults to -1. * * @return the fetched web page as a \0-terminated string, * or NULL if fetching the page fails. * Must be destroyed by caller if non-NULL. */ static char *executeWebMethod( char *inMethod, char *inURL, char *inBody, int *outContentLength, char **outFinalURL = NULL, char **outMimeType = NULL, long inTimeoutInMilliseconds = -1 ); }; #endif between-6+dfsg1.orig/minorGems/network/web/WebRequest.h0000640000175000017500000000257411435543336021725 0ustar pabspabs#ifndef WEB_REQUEST_INCLUDED #define WEB_REQUEST_INCLUDED #include "minorGems/network/Socket.h" #include "minorGems/network/HostAddress.h" #include "minorGems/network/LookupThread.h" // a non-blocking web request class WebRequest { public: // inMethod = GET, POST, etc. // inURL the url to retrieve // inBody the body of the request, can be NULL // request body must be in application/x-www-form-urlencoded format WebRequest( const char *inMethod, const char *inURL, const char *inBody ); // if request is not complete, destruction cancels it ~WebRequest(); // take anoter non-blocking step // return 1 if request complete // return -1 if request hit an error // return 0 if request still in-progress int step(); // gets the response body as a \0-terminated string char *getResult(); protected: char mError; char *mURL; char *mRequest; int mRequestPosition; SimpleVector mResponse; char mResultReady; char *mResult; HostAddress *mSuppliedAddress; HostAddress *mNumericalAddress; LookupThread *mLookupThread; Socket *mSock; }; #endif between-6+dfsg1.orig/minorGems/network/web/URLUtils.cpp0000640000175000017500000002200111435543336021640 0ustar pabspabs/* * Modification History * * 2002-May-10 Jason Rohrer * Created. * * 2002-May-11 Jason Rohrer * Added functions for hex encoding and decoding. * * 2002-May-12 Jason Rohrer * Added conversion for #, &, and ?. * Added conversion for CR and LF. * * 2002-August-1 Jason Rohrer * Added conversion for /, \, ., and :. * * 2002-September-12 Jason Rohrer * Added missing breaks. * * 2002-September-25 Jason Rohrer * Fixed a bug with the way + characters are handled. * Changed to trim the returned buffer. * * 2002-October-8 Jason Rohrer * Added functions for extracting query arguments. */ #include "URLUtils.h" #include "minorGems/util/stringUtils.h" #include "minorGems/util/SimpleVector.h" #include char *URLUtils::getRootServer( char *inURL ) { char *urlCopy = stringDuplicate( inURL ); char *endOfURLType = strstr( urlCopy, "://" ); char *returnString = NULL; if( endOfURLType != NULL ) { char *startOfRootServer = &( endOfURLType[ 3 ] ); char *endOfRootServer = strstr( startOfRootServer, "/" ); if( endOfRootServer != NULL ) { endOfRootServer[0] = '\0'; } returnString = stringDuplicate( startOfRootServer ); } delete [] urlCopy; return returnString; } char *URLUtils::getRootRelativePath( char *inURL ) { char *urlCopy = stringDuplicate( inURL ); char *endOfURLType = strstr( urlCopy, "://" ); char *returnString = NULL; if( endOfURLType != NULL ) { char *startOfRootServer = &( endOfURLType[ 3 ] ); char *endOfRootServer = strstr( startOfRootServer, "/" ); if( endOfRootServer == NULL ) { returnString = stringDuplicate( "/" ); } else { char *lastSlash = endOfRootServer; char *currentSlash = strstr( &( lastSlash[1] ), "/" ); while( currentSlash != NULL ) { lastSlash = currentSlash; currentSlash = strstr( &( lastSlash[1] ), "/" ); } // terminate string right after last slash lastSlash[1] = '\0'; returnString = stringDuplicate( endOfRootServer ); } } delete [] urlCopy; return returnString; } char *URLUtils::hexDecode( char *inString ) { // first run through string and replace any + characters with spaces char *workingString = stringDuplicate( inString ); char *plusLocation = strstr( workingString, "+" ); while( plusLocation != NULL ) { plusLocation[0] = ' '; plusLocation = strstr( plusLocation, "+" ); } int stringLength = strlen( workingString ); char *returnString = new char[ stringLength + 1 ]; int stringIndex = 0; int returnStringIndex = 0; while( stringIndex < stringLength + 1 ) { if( workingString[ stringIndex ] != '%' ) { // not a hex representation returnString[ returnStringIndex ] = workingString[ stringIndex ]; stringIndex++; returnStringIndex++; } else { // the start of hex char twoChars[2]; twoChars[0] = workingString[ stringIndex + 1 ]; twoChars[1]= workingString[ stringIndex + 2 ]; char summedChar = 0; for( int i=0; i<2; i++ ) { int shiftAmount = 4 * ( 1 - i ); switch( twoChars[i] ) { case '0': summedChar += 0x0 << shiftAmount; break; case '1': summedChar += 0x1 << shiftAmount; break; case '2': summedChar += 0x2 << shiftAmount; break; case '3': summedChar += 0x3 << shiftAmount; break; case '4': summedChar += 0x4 << shiftAmount; break; case '5': summedChar += 0x5 << shiftAmount; break; case '6': summedChar += 0x6 << shiftAmount; break; case '7': summedChar += 0x7 << shiftAmount; break; case '8': summedChar += 0x8 << shiftAmount; break; case '9': summedChar += 0x9 << shiftAmount; break; case 'A': summedChar += 0xA << shiftAmount; break; case 'B': summedChar += 0xB << shiftAmount; break; case 'C': summedChar += 0xC << shiftAmount; break; case 'D': summedChar += 0xD << shiftAmount; break; case 'E': summedChar += 0xE << shiftAmount; break; case 'F': summedChar += 0xF << shiftAmount; break; default: break; } } returnString[ returnStringIndex ] = summedChar; stringIndex += 3; returnStringIndex++; } } delete [] workingString; // trim the return string workingString = returnString; returnString = stringDuplicate( workingString ); delete [] workingString; return returnString; } char *URLUtils::hexEncode( char *inString ) { SimpleVector *returnStringVector = new SimpleVector(); int stringLength = strlen( inString ); int i; for( i=0; ipush_back( '%' ); returnStringVector->push_back( '0' ); returnStringVector->push_back( 'A' ); break; case '\r': returnStringVector->push_back( '%' ); returnStringVector->push_back( '0' ); returnStringVector->push_back( 'D' ); break; case '#': returnStringVector->push_back( '%' ); returnStringVector->push_back( '2' ); returnStringVector->push_back( '3' ); break; case '&': returnStringVector->push_back( '%' ); returnStringVector->push_back( '2' ); returnStringVector->push_back( '6' ); break; case '?': returnStringVector->push_back( '%' ); returnStringVector->push_back( '3' ); returnStringVector->push_back( 'F' ); break; case '\\': returnStringVector->push_back( '%' ); returnStringVector->push_back( '5' ); returnStringVector->push_back( 'C' ); break; case '/': returnStringVector->push_back( '%' ); returnStringVector->push_back( '2' ); returnStringVector->push_back( 'F' ); break; case ':': returnStringVector->push_back( '%' ); returnStringVector->push_back( '3' ); returnStringVector->push_back( 'A' ); break; case '.': returnStringVector->push_back( '%' ); returnStringVector->push_back( '2' ); returnStringVector->push_back( 'E' ); break; case '+': returnStringVector->push_back( '%' ); returnStringVector->push_back( '2' ); returnStringVector->push_back( 'B' ); break; case ' ': returnStringVector->push_back( '+' ); break; default: returnStringVector->push_back( inString[i] ); break; } } int numChars = returnStringVector->size(); char *returnString = new char[ numChars + 1 ]; for( i=0; igetElement( i ) ); } returnString[ numChars ] = '\0'; delete returnStringVector; return returnString; } char *URLUtils::extractArgument( char *inHaystack, char *inArgName ) { char *argNameWithEquals = new char[ strlen( inArgName ) + 2 ]; sprintf( argNameWithEquals, "%s%s", inArgName, "=" ); char *haystackCopy = stringDuplicate( inHaystack ); char *pointerToArgStart = strstr( haystackCopy, argNameWithEquals ); if( pointerToArgStart == NULL ) { delete [] haystackCopy; delete [] argNameWithEquals; return NULL; } else { char *pointerToArgEnd = strstr( pointerToArgStart, "&" ); if( pointerToArgEnd != NULL ) { // terminate string at arg end pointerToArgEnd[0] = '\0'; } // else entire remainder of string is argument char *pointerToArgValue = &( pointerToArgStart[ strlen( argNameWithEquals ) ] ); // trim string char *returnString = stringDuplicate( pointerToArgValue ); delete [] argNameWithEquals; delete [] haystackCopy; return returnString; } } char *URLUtils::extractArgumentRemoveHex( char *inHaystack, char *inArgName ) { char *extractedArg = extractArgument( inHaystack, inArgName ); if( extractedArg != NULL ) { char *convertedArg = URLUtils::hexDecode( extractedArg ); delete [] extractedArg; return convertedArg; } else { return NULL; } } between-6+dfsg1.orig/minorGems/network/web/WebRequest.cpp0000640000175000017500000002460211435543336022254 0ustar pabspabs#include "WebRequest.h" #include "minorGems/util/stringUtils.h" #include "minorGems/util/StringBufferOutputStream.h" #include "minorGems/network/SocketClient.h" WebRequest::WebRequest( const char *inMethod, const char *inURL, const char *inBody ) : mError( false ), mURL( stringDuplicate( inURL ) ), mRequest( NULL ), mRequestPosition( -1 ), mResultReady( false ), mResult( NULL ), mSock( NULL ) { const char *startString = "http://"; char *urlCopy = stringDuplicate( inURL ); char *urlStart = stringLocateIgnoreCase( urlCopy, startString ); char *serverStart; if( urlStart == NULL ) { // no http:// at start of URL serverStart = urlCopy; } else { serverStart = &( urlStart[ strlen( startString ) ] ); } // find the first occurrence of "/", which is the end of the // server name char *serverNameCopy = stringDuplicate( serverStart ); char *serverEnd = strstr( serverNameCopy, "/" ); char *getPath = strstr( serverStart, "/" ); if( serverEnd == NULL ) { serverEnd = &( serverStart[ strlen( serverStart ) ] ); getPath = (char *)"/"; } // terminate the url here to extract the server name serverEnd[0] = '\0'; int portNumber = 80; // look for a port number char *colon = strstr( serverNameCopy, ":" ); if( colon != NULL ) { char *portNumberString = &( colon[1] ); int numRead = sscanf( portNumberString, "%d", & portNumber ); if( numRead != 1 ) { portNumber = 80; } // terminate the name here so port isn't taken as part // of the address colon[0] = '\0'; } mSuppliedAddress = new HostAddress( stringDuplicate( serverNameCopy ), portNumber ); mNumericalAddress = NULL; mLookupThread = NULL; // launch right into name lookup mLookupThread = new LookupThread( mSuppliedAddress ); mSock = NULL; // compose the request into a buffered stream StringBufferOutputStream tempStream; tempStream.writeString( inMethod ); tempStream.writeString( " " ); tempStream.writeString( getPath ); tempStream.writeString( " HTTP/1.0\r\n" ); tempStream.writeString( "Host: " ); tempStream.writeString( serverNameCopy ); tempStream.writeString( "\r\n" ); if( inBody != NULL ) { char *lengthString = autoSprintf( "Content-Length: %d\r\n", strlen( inBody ) ); tempStream.writeString( lengthString ); delete [] lengthString; tempStream.writeString( "Content-Type: application/x-www-form-urlencoded\r\n\r\n" ); tempStream.writeString( inBody ); } else { tempStream.writeString( "\r\n" ); } mRequest = tempStream.getString(); mRequestPosition = 0; delete [] serverNameCopy; delete [] urlCopy; } WebRequest::~WebRequest() { if( mLookupThread != NULL ) { // this might block delete mLookupThread; } delete mSuppliedAddress; if( mNumericalAddress != NULL ) { delete mNumericalAddress; } delete [] mURL; if( mSock != NULL ) { delete mSock; } if( mRequest != NULL ) { delete [] mRequest; } if( mResult != NULL ) { delete [] mResult; } } int WebRequest::step() { if( mError ) { return -1; } if( mSock == NULL ) { // we know mLookupThread is not NULL if we get here if( mLookupThread->isLookupDone() ) { mError = true; mNumericalAddress = mLookupThread->getResult(); if( mNumericalAddress != NULL ) { // use timeout of 0 for non-blocking // will be set to true if we time out while connecting char timedOut; mSock = SocketClient::connectToServer( mNumericalAddress, 0, &timedOut ); if( mSock != NULL ) { mError = false; } } if( mError ) { // lookup or socket construction failed if( mNumericalAddress == NULL ) { printf( "Error: " "WebRequest failed to lookup %s\n", mSuppliedAddress->mAddressString ); } else { printf( "Error: " "WebRequest failed to construct " "socket to %s:%d\n", mNumericalAddress->mAddressString, mNumericalAddress->mPort ); } return -1; } } else { // still looking up return 0; } } int connectStatus = mSock->isConnected(); if( connectStatus == 0 ) { // still trying to connect return 0; } else if( connectStatus < 0 ) { // failed to connect mError = true; printf( "Error: " "WebRequest failed to connect to %s:%d\n", mNumericalAddress->mAddressString, mNumericalAddress->mPort ); return -1; } else if( connectStatus == 1 ) { // connected if( mRequestPosition < (int)( strlen( mRequest ) ) ) { // try to send more char *remainingRequest = &( mRequest[ mRequestPosition ] ); int numSent = mSock->send( (unsigned char *)remainingRequest, strlen( remainingRequest ), // non-blocking false ); if( numSent == -1 ) { mError = true; printf( "Error: " "WebRequest failed to connect to " "send full request\n" ); return -1; } if( numSent == -2 ) { return 0; } mRequestPosition += numSent; // don't start looking for response in same step, // even if we just sent the entire request // in practice, it's never ready that fast return 0; } else if( mResultReady ) { return 1; } else { // done sending request // still receiving response long bufferLength = 5000; unsigned char *buffer = new unsigned char[ bufferLength ]; // non-blocking // keep reading as long as we get full buffers int numRead = bufferLength; while( numRead > 0 ) { numRead = mSock->receive( buffer, bufferLength, 0 ); if( numRead > 0 ) { for( int i=0; i /** * A class that can resolve file extensions to mime types. * * @author Jason Rohrer */ class MimeTyper { public: /** * Constructs a mime typer. * * @param inFileName the configuration file from, or * NULL to specify the default file name, "mime.ini". * File name is relative to the settings directory. * Defaults to NULL. * Must be destroyed by caller if non-NULL and non-const. */ MimeTyper( char *inConfigFileName = NULL ); ~MimeTyper(); /** * Gets a mime type string from a file extension string. * * @param inFileExtension a \0-terminated string containing * a file extension, including the '.' * Must be destroyed by caller if non-const. * * @return the mime type as a \0-terminated string, * or NULL if there is no match. * Must be destroyed by caller if non-NULL. */ char *getMimeType( char *inFileExtension ); /** * Gets a mime type string from a file name. * * @param inFileName a \0-terminated string containing * a file name with extension. * Must be destroyed by caller if non-const. * * @return the mime type as a \0-terminated string, * or NULL if there is no match. * Must be destroyed by caller if non-NULL. */ char *getFileNameMimeType( char *inFileName ); protected: // a string containing all types read from the configuration file char *mMimeTypesString; }; #endif between-6+dfsg1.orig/minorGems/network/web/WebClient.cpp0000640000175000017500000002730411435543336022044 0ustar pabspabs/* * Modification History * * 2002-May-5 Jason Rohrer * Created. * Changed to default to http:// if no URL type specified. * Added support for the Host: header. * * 2002-May-7 Jason Rohrer * Added support for pages that have been moved permanently. * * 2002-May-12 Jason Rohrer * Added support for the Object Moved message type. * Added support for fetching the final (after redirects) URL. * Fixed a memory leak. * * 2002-May-26 Jason Rohrer * Added support for fetching mime types and content length. * Added a function for fetching MIME types alone. * Changed to use case-ignoring string comparison where appropriate. * * 2002-July-19 Jason Rohrer * Changed to deal with not found headers properly. * * 2002-August-5 Jason Rohrer * Fixed a typo. * * 2002-November-10 Jason Rohrer * Added a fix to deal with a slashdot bug. * * 2006-January-22 Jason Rohrer * Added support for timeouts. * * 2008-September-25 Jason Rohrer * Added POST. */ #include "WebClient.h" #include "minorGems/util/log/AppLog.h" #include "minorGems/util/stringUtils.h" #include "minorGems/util/SimpleVector.h" char *WebClient::getWebPage( char *inURL, int *outContentLength, char **outFinalURL, char **outMimeType, long inTimeoutInMilliseconds ) { return executeWebMethod( "GET", inURL, NULL, outContentLength, outFinalURL, outMimeType, inTimeoutInMilliseconds ); } char *WebClient::getWebPagePost( char *inURL, char *inPostBody, int *outContentLength, char **outFinalURL, char **outMimeType, long inTimeoutInMilliseconds ) { return executeWebMethod( "POST", inURL, inPostBody, outContentLength, outFinalURL, outMimeType, inTimeoutInMilliseconds ); } char *WebClient::getMimeType( char *inURL ) { int contentLength; char *mimeType; char *content = executeWebMethod( "HEAD", inURL, NULL, &contentLength, NULL, &mimeType ); if( content != NULL ) { delete [] content; } return mimeType; } char *WebClient::executeWebMethod( char *inMethod, char *inURL, char *inBody, int *outContentLength, char **outFinalURL, char **outMimeType, long inTimeoutInMilliseconds ) { char *returnString = NULL; char *startString = "http://"; char *urlCopy = stringDuplicate( inURL ); char *urlStart = stringLocateIgnoreCase( urlCopy, startString ); char *serverStart; if( urlStart == NULL ) { // no http:// at start of URL serverStart = urlCopy; } else { serverStart = &( urlStart[ strlen( startString ) ] ); } // find the first occurrence of "/", which is the end of the // server name char *serverNameCopy = stringDuplicate( serverStart ); char *serverEnd = strstr( serverNameCopy, "/" ); char *getPath = strstr( serverStart, "/" ); if( serverEnd == NULL ) { serverEnd = &( serverStart[ strlen( serverStart ) ] ); getPath = "/"; } // terminate the url here to extract the server name serverEnd[0] = '\0'; int portNumber = 80; // look for a port number char *colon = strstr( serverNameCopy, ":" ); if( colon != NULL ) { char *portNumberString = &( colon[1] ); int numRead = sscanf( portNumberString, "%d", & portNumber ); if( numRead != 1 ) { portNumber = 80; } // terminate the name here so port isn't taken as part // of the address colon[0] = '\0'; } HostAddress *host = new HostAddress( stringDuplicate( serverNameCopy ), portNumber ); // will be set to true if we time out while connecting char timedOut; Socket *sock = SocketClient::connectToServer( host, inTimeoutInMilliseconds, &timedOut ); char *finalURL = stringDuplicate( inURL ); char *mimeType = NULL; int receivedLength = 0; if( sock != NULL ) { SocketStream *stream = new SocketStream( sock ); // reuse the same timeout for read operations stream->setReadTimeout( inTimeoutInMilliseconds ); // method and trailing space need to be sent in the same // buffer to work around a bug in certain web servers char *methodWithSpace = new char[ strlen( inMethod ) + 2 ]; sprintf( methodWithSpace, "%s ", inMethod ); // send the request stream->writeString( methodWithSpace ); stream->writeString( getPath ); stream->writeString( " HTTP/1.0\r\n" ); stream->writeString( "Host: " ); stream->writeString( serverNameCopy ); stream->writeString( "\r\n" ); if( inBody != NULL ) { char *lengthString = autoSprintf( "Content-Length: %d\r\n", strlen( inBody ) ); stream->writeString( lengthString ); delete [] lengthString; stream->writeString( "Content-Type: application/x-www-form-urlencoded\r\n\r\n" ); stream->writeString( inBody ); } else { stream->writeString( "\r\n" ); } delete [] methodWithSpace; // the simplest thing to do is to read upto the // socket close first, then extract the content char *received = receiveData( stream, &receivedLength ); char *content = NULL; char notFound = false; if( stringLocateIgnoreCase( received, "404 Not Found" ) != NULL ) { notFound = true; } // watch for redirection headers if( stringLocateIgnoreCase( received, "302 Found" ) != NULL || stringLocateIgnoreCase( received, "301 Moved Permanently" ) != NULL || stringLocateIgnoreCase( received, "302 Object Moved" ) != NULL ) { // call ourself recursively to fetch the redirection char *locationTag = "Location: "; char *locationTagStart = stringLocateIgnoreCase( received, locationTag ); if( locationTagStart != NULL ) { char *locationStart = &( locationTagStart[ strlen( locationTag ) ] ); // replace next \r with \0 char *nextChar = locationStart; while( nextChar[0] != '\r' && nextChar[0] != '\0' ) { nextChar = &( nextChar[1] ); } nextChar[0] = '\0'; char *newFinalURL; content = getWebPage( locationStart, &receivedLength, &newFinalURL, &mimeType ); delete [] finalURL; finalURL = newFinalURL; if( content == NULL ) { // not found recursively notFound = true; } } } char *contentStartString = "\r\n\r\n"; char *contentTypeStartString = "Content-type:"; if( notFound ) { returnString = NULL; } else { if( content == NULL ) { // scan for content type char *contentTypeStartMarker = stringLocateIgnoreCase( received, contentTypeStartString ); if( contentTypeStartMarker != NULL ) { // skip marker char *contentTypeStart = &( contentTypeStartMarker[ strlen( contentTypeStartString ) ] ); // extract content type // make sure the buffer is big enough char *contentType = new char[ strlen( contentTypeStartMarker ) ]; int numRead = sscanf( contentTypeStart, "%s", contentType ); if( numRead == 1 ) { // trim mimeType = stringDuplicate( contentType ); } delete [] contentType; } // extract the content from what we've received char *contentStart = strstr( received, contentStartString ); if( contentStart != NULL ) { content = &( contentStart[ strlen( contentStartString ) ] ); receivedLength = receivedLength - strlen( contentStartString ) - ( (int)contentStart - (int)received ); returnString = new char[ receivedLength + 1 ]; returnString = (char*)memcpy( returnString, content, receivedLength ); returnString[ receivedLength ] = '\0'; } } else { // we already obtained our content recursively returnString = new char[ receivedLength + 1 ]; returnString = (char*)memcpy( returnString, content, receivedLength ); returnString[ receivedLength ] = '\0'; delete [] content; } } delete [] received; delete stream; delete sock; } delete host; delete [] serverNameCopy; delete [] urlCopy; if( outFinalURL != NULL ) { *outFinalURL = finalURL; } else { delete [] finalURL; } if( outMimeType != NULL ) { *outMimeType = mimeType; } else { if( mimeType != NULL ) { delete [] mimeType; } } *outContentLength = receivedLength; return returnString; } char *WebClient::receiveData( SocketStream *inSocketStream, int *outContentLength ) { SimpleVector *receivedVector = new SimpleVector(); char connectionBroken = false; long bufferLength = 5000; unsigned char *buffer = new unsigned char[ bufferLength ]; while( !connectionBroken ) { int numRead = inSocketStream->read( buffer, bufferLength ); if( numRead != bufferLength ) { connectionBroken = true; } if( numRead > 0 ) { for( int i=0; ipush_back( buffer[i] ); } } } delete [] buffer; // copy our vector into an array int receivedSize = receivedVector->size(); char *received = new char[ receivedSize + 1 ]; for( int i=0; igetElement( i ) ); } received[ receivedSize ] = '\0'; delete receivedVector; *outContentLength = receivedSize; return received; } between-6+dfsg1.orig/minorGems/network/web/MimeTyper.cpp0000640000175000017500000000757611435543336022114 0ustar pabspabs/* * Modification History * * 2002-April-20 Jason Rohrer * Created. * * 2002-April-22 Jason Rohrer * Fixed a bug with the mime type string. * * 2002-April-30 Jason Rohrer * Removed an unused variable. * * 2002-September-17 Jason Rohrer * Moved mime.ini into settings directory. * * 2002-October-7 Jason Rohrer * Added a function for getting mime types from file names. * * 2003-September-1 Jason Rohrer * Copied into minorGems from the konspire2b project. */ #include "MimeTyper.h" #include "minorGems/util/stringUtils.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/FileInputStream.h" #include #include MimeTyper::MimeTyper( char *inConfigFileName ) { File *configFile; char **pathSteps = new char*[1]; pathSteps[0] = "settings"; if( inConfigFileName == NULL ) { configFile = new File( new Path( pathSteps, 1, false ), "mime.ini" ); } else { configFile = new File( new Path( pathSteps, 1, false ), inConfigFileName ); } delete [] pathSteps; if( !configFile->exists() ) { char *name = configFile->getFileName(); printf( "Error: MIME config file %s does not exist.\n", name ); delete [] name; mMimeTypesString = new char[ 1 ]; mMimeTypesString[0] = '\0'; } else { int length = configFile->getLength(); mMimeTypesString = new char[ length + 1 ]; char *name = configFile->getFileName(); FileInputStream *inStream = new FileInputStream( configFile ); int numRead = inStream->read( (unsigned char *)mMimeTypesString, length ); if( numRead != length ) { printf( "Error reading from MIME config file %s.\n", name ); delete [] mMimeTypesString; mMimeTypesString = new char[ 1 ]; mMimeTypesString[0] = '\0'; } else { mMimeTypesString[ length ] = '\0'; } delete [] name; delete inStream; } delete configFile; } MimeTyper::~MimeTyper() { if( mMimeTypesString != NULL ) { delete [] mMimeTypesString; } } char *MimeTyper::getMimeType( char *inFileExtension ) { char *extensionMatch = strstr( mMimeTypesString, inFileExtension ); if( extensionMatch ) { // we should be able to scan two strings from // the position of the match // the first string should be the extension // the second string should be the mime type // make sure buffer is big enough char *buffer = new char[ strlen( mMimeTypesString ) + 1 ]; int numRead = sscanf( extensionMatch, "%s", buffer ); char *returnString = NULL; if( numRead == 1 ) { int numToSkip = strlen( buffer ); // skip first string token (extension) // and read next string token (mime type) numRead = sscanf( &( extensionMatch[ numToSkip ] ), "%s", buffer ); if( numRead == 1 ) { returnString = stringDuplicate( buffer ); } } delete [] buffer; return returnString; } else { return NULL; } } char *MimeTyper::getFileNameMimeType( char *inFileName ) { int fileNameLength = strlen( inFileName ); int lastPeriodIndex = -1; for( int i=0; i #include /** * A class that handles permissions for received connections. * * @author Jason Rohrer. */ class ConnectionPermissionHandler { public: /** * Constructs a handler. */ ConnectionPermissionHandler(); ~ConnectionPermissionHandler(); /** * Gets whether a connection is permitted. * * @param inAddress the address of the host connecting. * Must be destroyed by caller. * * @return true iff a connection is allowed. */ char isPermitted( HostAddress *inAddress ); private: SimpleVector *mPermittedAddresses; SimpleVector *mPermittedPatterns; }; #endif between-6+dfsg1.orig/minorGems/network/web/server/RequestHandlingThread.h0000640000175000017500000000600311435543336025361 0ustar pabspabs/* * Modification History * * 2002-March-12 Jason Rohrer * Created. * * 2002-March-29 Jason Rohrer * Fixed include order. * * 2002-August-2 Jason Rohrer * Added use of ConnectionPermissionHandler. * * 2003-September-5 Jason Rohrer * Moved into minorGems. */ #ifndef REQUEST_HANDLING_THREAD_INCLUDED #define REQUEST_HANDLING_THREAD_INCLUDED #include "PageGenerator.h" #include "ConnectionPermissionHandler.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/FileInputStream.h" #include "minorGems/network/Socket.h" #include "minorGems/network/SocketStream.h" #include "minorGems/system/Thread.h" #include "minorGems/system/MutexLock.h" #include #include #include #define REQUEST_HANDLING_THREAD_BUFFER_SIZE 4096 /** * Request handler for WebServer. * * @author Jason Rohrer. */ class RequestHandlingThread : public Thread { public: /** * Construct a handler. * * @param inSocket the socket to send the requested * file trough. Is destroyed before this thread terminates. * @param inGenerator the class that will generate the * page content. * Is not destroyed by this class. * @param inConnectionPermissionHandler the class that will * grant connection permissions * Is not destroyed by this class. */ RequestHandlingThread( Socket *inSocket, PageGenerator *inGenerator, ConnectionPermissionHandler *inConnectionPermissionHandler); ~RequestHandlingThread(); /** * Returns true if this handler is done and ready to be destroyed. * * Synchronized, so may block. * * @return true if this handler is done and ready to be destroyed. */ char isDone(); /** * Gets a string representation of the current time. * * @return a timestamp string. Must be destroyed by caller. */ static char* getTimestamp(); // implements the Thread interface virtual void run(); private: Socket *mSocket; PageGenerator *mGenerator; ConnectionPermissionHandler *mConnectionPermissionHandler; MutexLock *mDoneLock; char mDone; /** * Sends an HTTP "not found" message with a "not found" web page. * * @param inStream the stream to send the not found page to. * @param inFileName the name of the requested file, * or NULL. */ void sendNotFoundPage( SocketStream *inStream, char *inFileName ); /** * Sends a "bad request" web page. * * @param inStream the stream to send the page to. */ void sendBadRequest( SocketStream *inStream ); }; #endif between-6+dfsg1.orig/minorGems/network/web/server/ConnectionPermissionHandler.cpp0000640000175000017500000000641011435543336027137 0ustar pabspabs/* * Modification History * * 2002-August-2 Jason Rohrer * Created. * Fixed a buffer size error. * * 2002-September-17 Jason Rohrer * Changed to use the SettingsManager. * * 2002-November-9 Jason Rohrer * Added support for matching address patterns. * * 2003-September-5 Jason Rohrer * Moved into minorGems. */ #include "ConnectionPermissionHandler.h" #include "minorGems/io/file/File.h" #include "minorGems/util/SettingsManager.h" ConnectionPermissionHandler::ConnectionPermissionHandler() { SimpleVector *addressVector = SettingsManager::getSetting( "allowedWebHosts" ); int numAddresses = addressVector->size(); mPermittedAddresses = new SimpleVector(); mPermittedPatterns = new SimpleVector(); for( int i=0; igetElement( i ) ); char *starLocation = strstr( addressString, "*" ); if( starLocation == NULL ) { // an address mPermittedAddresses->push_back( new HostAddress( addressString, 0 ) ); } else { // an address pattern mPermittedPatterns->push_back( addressString ); } } delete addressVector; } ConnectionPermissionHandler::~ConnectionPermissionHandler() { int numAddresses = mPermittedAddresses->size(); int i; for( i=0; igetElement( i ) ); delete address; } int numPatterns = mPermittedPatterns->size(); for( i=0; igetElement( i ) ); delete [] pattern; } delete mPermittedAddresses; delete mPermittedPatterns; } char ConnectionPermissionHandler::isPermitted( HostAddress *inAddress ) { int numAddresses = mPermittedAddresses->size(); int i; for( i=0; igetElement( i ) ); if( address->equals( inAddress ) ) { return true; } } // didn't match any address exactly // check if it matches one of our patterns HostAddress* numericalAddress = inAddress->getNumericalAddress(); if( numericalAddress == NULL ) { return false; } char *addressString = numericalAddress->mAddressString; int numPatterns = mPermittedPatterns->size(); char foundMatch = false; for( i=0; igetElement( i ) ); int patternLength = strlen( pattern ); int addressLength = strlen( addressString ); char done = false; for( int j=0; jlock(); tempDone = mDone; mDoneLock->unlock(); return mDone; } // example HTTP request and response /* GET /images/title_homepage4.gif HTTP/1.0 HTTP/1.0 200 OK Date: Fri, 11 May 2001 18:05:08 GMT Server: GWS/1.10 Connection: close Expires: Sun, 17 Jan 2038 19:14:07 GMT Content-Length: 7963 Content-Type: image/gif Last-Modified: Tue, 21 Nov 2000 16:20:07 GMT GIF89a1s */ void RequestHandlingThread::run() { HostAddress *receivedAddress = mSocket->getRemoteHostAddress(); if( receivedAddress == NULL ) { printf( "Failed to obtain host address, so " "refusing web connection.\n" ); // refuse delete mSocket; // flag that we're done mDoneLock->lock(); mDone = true; mDoneLock->unlock(); return; } else if( ! mConnectionPermissionHandler->isPermitted( receivedAddress ) ) { printf( "Refusing web connection from: " ); receivedAddress->print(); printf( "\n" ); // not permitted delete mSocket; delete receivedAddress; // flag that we're done mDoneLock->lock(); mDone = true; mDoneLock->unlock(); return; } // else permitted delete receivedAddress; int maxLength = 5000; // first, receive the request and parse it SocketStream *sockStream = new SocketStream( mSocket ); int requestBufferLength = maxLength; char *requestBuffer = new char[requestBufferLength]; int requestBufferIndex = 0; // read until we see two \r\n 's in a row unsigned char *charRead = new unsigned char[1]; charRead[0] = 0; char requestDone = false; char error = false; // _we_ actually only care about the first line of // the request, but we need to read the entire request // to make the other host happy char firstLineDone = false; int numRead = 0; while( !requestDone && !error ) { while( charRead[0] != 13 && !error ) { numRead = sockStream->read( charRead, 1 ); if( !firstLineDone ) { if( numRead != 1 ) { error = true; sendBadRequest( sockStream ); } // read data into our buffer else if( requestBufferIndex < requestBufferLength ) { requestBuffer[ requestBufferIndex ] = charRead[0]; requestBufferIndex++; if( charRead[0] == 13 ) { firstLineDone = true; } } else { error = true; sendBadRequest( sockStream ); } } } if( !error ) { // look for rest of double \r\n // this will effectively skip other lines in the request, // since we don't care about them numRead = sockStream->read( charRead, 1 ); if( charRead[0] == 10 && numRead == 1 ) { numRead = sockStream->read( charRead, 1 ); if( charRead[0] == 13 && numRead == 1 ) { numRead = sockStream->read( charRead, 1 ); if( charRead[0] == 10 && numRead == 1 ) { requestDone = true; } } } if( numRead != 1 ) { error = true; sendBadRequest( sockStream ); } } } // \0 terminate the request buffer if( requestBufferIndex < requestBufferLength ) { requestBuffer[ requestBufferIndex ] = '\0'; } else { requestBuffer[ requestBufferLength - 1 ] = '\0'; } if( !error ) { // at this point, we have received the entire // request, and stored the most important part in // requestBuffer // if maxLength = 500, // formatString = "%499s" // used to limit length of scanned string char *formatString = new char[ 20 ]; sprintf( formatString, "%%%ds", maxLength - 1 ); // the second string scanned from the buffer should // be the file path requested char *filePathBuffer = new char[ maxLength ]; int numRead = sscanf( requestBuffer, formatString, filePathBuffer ); if( numRead != 1 || strcmp( filePathBuffer, "GET" ) != 0 ) { // an invalid request error = true; sendBadRequest( sockStream ); } else { // a proper GET request // skip the GET and read the file name numRead = sscanf( &( requestBuffer[3] ), formatString, filePathBuffer ); if( numRead != 1 ) { error = true; sendBadRequest( sockStream ); } } delete [] requestBuffer; delete [] charRead; delete [] formatString; if( !error ) { // now we have the requested file string sockStream->writeString( "HTTP/1.0 200 OK\r\n" ); char *mimeType = mGenerator->getMimeType( filePathBuffer ); sockStream->writeString( "Content-Type: " ); sockStream->writeString( mimeType ); sockStream->writeString( "\r\n" ); delete [] mimeType; // even if the client requests a keep-alive, we force a close sockStream->writeString( "Connection: close" ); // finish header sockStream->writeString( "\r\n\r\n" ); // pass it to our page generator, which will send the content mGenerator->generatePage( filePathBuffer, sockStream ); } delete [] filePathBuffer; } else { delete [] requestBuffer; delete [] charRead; } delete sockStream; delete mSocket; // flag that we're done mDoneLock->lock(); mDone = true; mDoneLock->unlock(); } void RequestHandlingThread::sendNotFoundPage( SocketStream *inStream, char *inFileName ) { // example "not found" response /* HTTP/1.0 404 Not Found Date: Fri, 11 May 2001 18:26:16 GMT Server: GWS/1.10 Connection: close Set-Cookie: PREF=ID=3300d4623bf73a57:TM=989605576:LM=989605576; domain=.google.com; path=/; expires=Sun, 17-Jan-2038 19:14:07 GMT Content-Length: 142 Content-Type: text/html Not Found

404 Not Found

The requested URL /fjfj was not found on this server. */ char *buffer = new char[500]; if( inFileName != NULL ) { sprintf( buffer, "HTTP/1.0 404 Not Found\r\n\r\n" "

404 Not Found

The requested file " "%s was not found\r\n", inFileName ); } else { sprintf( buffer, "HTTP/1.0 404 Not Found\r\n\r\n" "

404 Not Found

The requested " "file was not found\r\n" ); } inStream->write( (unsigned char *)buffer, strlen( buffer ) ); delete [] buffer; } void RequestHandlingThread::sendBadRequest( SocketStream *inStream ) { // exampl "bad request" response /* Bad Request

400 Bad Request

Your client has issued a malformed or illegal request. */ char *buffer = new char[500]; sprintf( buffer, "

400 Bad Request

" "Your client has issued a malformed or illegal request." "\r\n" ); inStream->write( (unsigned char *)buffer, strlen( buffer ) ); delete [] buffer; } char* RequestHandlingThread::getTimestamp() { char *stampBuffer = new char[99]; time_t t = time( NULL ); char *asciiTime = ctime( &t ); // this time string ends with a newline... // get rid of it asciiTime[ strlen(asciiTime) - 1 ] = '\0'; sprintf( stampBuffer, "[%s]", asciiTime ); // delete [] asciiTime; return stampBuffer; } between-6+dfsg1.orig/minorGems/network/web/server/WebServer.cpp0000640000175000017500000000476111435543336023404 0ustar pabspabs/* * Modification History * * 2002-March-12 Jason Rohrer * Created. * * 2002-April-5 Jason Rohrer * Changed to extend StopSignalThread. * Added timeouts to socket accept to support checking for stop signal. * * 2002-August-2 Jason Rohrer * Added use of ConnectionPermissionHandler. * * 2002-August-6 Jason Rohrer * Changed member init order. * * 2002-September-17 Jason Rohrer * Removed argument to ConnectionPermissionHandler constructor. * * 2003-September-5 Jason Rohrer * Moved into minorGems. */ #include "WebServer.h" #include "minorGems/util/log/AppLog.h" WebServer::WebServer( int inPort, PageGenerator *inGenerator ) : mPortNumber( inPort ), mMaxQueuedConnections( 100 ), mThreadHandler( new ThreadHandlingThread() ), mPageGenerator( inGenerator ), mConnectionPermissionHandler( new ConnectionPermissionHandler() ) { mServer = new SocketServer( mPortNumber, mMaxQueuedConnections ); this->start(); } WebServer::~WebServer() { stop(); join(); delete mServer; delete mThreadHandler; delete mPageGenerator; delete mConnectionPermissionHandler; } void WebServer::run() { char *logMessage = new char[100]; sprintf( logMessage, "Listening for connections on port %d\n", mPortNumber ); AppLog::info( "WebServer", logMessage ); delete [] logMessage; char acceptFailed = false; // main server loop while( !isStopped() && !acceptFailed ) { char timedOut = true; // 5 seconds long timeout = 5000; Socket *sock; AppLog::info( "WebServer", "Waiting for connection." ); while( timedOut && !isStopped() ) { sock = mServer->acceptConnection( timeout, &timedOut ); } if( sock != NULL ) { AppLog::info( "WebServer", "Connection received." ); RequestHandlingThread *thread = new RequestHandlingThread( sock, mPageGenerator, mConnectionPermissionHandler ); thread->start(); mThreadHandler->addThread( thread ); } else if( isStopped() ) { AppLog::info( "WebServer", "Received stop signal." ); } else { AppLog::error( "WebServer", "Accepting a connection failed." ); acceptFailed = true; } } } between-6+dfsg1.orig/minorGems/network/web/server/ThreadHandlingThread.h0000640000175000017500000000256011435543336025144 0ustar pabspabs/* * Modification History * * 2002-March-12 Jason Rohrer * Created. * * 2002-April-5 Jason Rohrer * Changed to extend StopSignalThread. * * 2003-September-5 Jason Rohrer * Moved into minorGems. */ #ifndef THREAD_HANDLING_THREAD_INCLUDED #define THREAD_HANDLING_THREAD_INCLUDED #include "RequestHandlingThread.h" #include "minorGems/system/StopSignalThread.h" #include "minorGems/system/MutexLock.h" #include "minorGems/util/SimpleVector.h" #include #include /** * Thread handler for the microWeb server. Runs periodically * and checks for finished threads that can be deleted. * * @author Jason Rohrer. */ class ThreadHandlingThread : public StopSignalThread { public: /** * Constructs and starts a handler. */ ThreadHandlingThread(); /** * Stops and destroys this handler. */ ~ThreadHandlingThread(); /** * Adds a thread to the set managed by this handler. * * @param inThread the thread to add. */ void addThread( RequestHandlingThread *inThread ); // implements the Thread interface virtual void run(); private: SimpleVector *mThreadVector; MutexLock *mLock; }; #endif between-6+dfsg1.orig/minorGems/network/web/server/WebServer.h0000640000175000017500000000326411435543336023046 0ustar pabspabs/* * Modification History * * 2002-March-12 Jason Rohrer * Created. * * 2002-March-29 Jason Rohrer * Fixed include order. * * 2002-April-5 Jason Rohrer * Changed to extend StopSignalThread. * * 2002-August-2 Jason Rohrer * Added use of ConnectionPermissionHandler. * * 2003-September-5 Jason Rohrer * Moved into minorGems. */ #ifndef WEB_SERVER_INCLUDED #define WEB_SERVER_INCLUDED #include "PageGenerator.h" #include "ConnectionPermissionHandler.h" #include "minorGems/network/Socket.h" #include "minorGems/network/SocketServer.h" #include "minorGems/network/SocketStream.h" #include "RequestHandlingThread.h" #include "ThreadHandlingThread.h" #include "minorGems/system/StopSignalThread.h" #include #include /** * A class that implements a basic web server. * * @author Jason Rohrer. */ class WebServer : public StopSignalThread { public: /** * Constructs an starts this server. * * @param inPort the port to listen on. * @param inGenerator the class to use for generating pages. * Will be destroyed when this class is destroyed. */ WebServer( int inPort, PageGenerator *inGenerator ); /** * Stops and destroys this server. */ ~WebServer(); // implements the Thread::run() interface void run(); private: int mPortNumber; int mMaxQueuedConnections; SocketServer *mServer; ThreadHandlingThread *mThreadHandler; PageGenerator *mPageGenerator; ConnectionPermissionHandler *mConnectionPermissionHandler; }; #endif between-6+dfsg1.orig/minorGems/network/web/server/ThreadHandlingThread.cpp0000640000175000017500000000471511435543336025503 0ustar pabspabs/* * Modification History * * 2002-March-12 Jason Rohrer * Created. * * 2002-April-5 Jason Rohrer * Changed to extend StopSignalThread. * * 2002-August-6 Jason Rohrer * Changed member init order. * * 2003-September-5 Jason Rohrer * Moved into minorGems. */ #include "ThreadHandlingThread.h" ThreadHandlingThread::ThreadHandlingThread() : mThreadVector( new SimpleVector() ), mLock( new MutexLock() ) { this->start(); } ThreadHandlingThread::~ThreadHandlingThread() { stop(); join(); mLock->lock(); int numThreads = mThreadVector->size(); // join each thread and delete it for( int i=0; igetElement( i ) ); thread->join(); delete thread; } delete mThreadVector; mLock->unlock(); delete mLock; } void ThreadHandlingThread::addThread( RequestHandlingThread *inThread ) { mLock->lock(); mThreadVector->push_back( inThread ); mLock->unlock(); } void ThreadHandlingThread::run() { while( !isStopped() ) { // sleep for 5 seconds sleep( 5000 ); // printf( "Thread handler looking for finished threads\n" ); // look for threads that need to be deleted mLock->lock(); char threadFound = true; // examine each thread while( threadFound ) { threadFound = false; int numThreads = mThreadVector->size(); for( int i=0; igetElement( i ) ); if( thread->isDone() ) { // join the thread before destroying it // to prevent memory leaks thread->join(); // remove the thread from the vector and delete it // printf( "deleting a thread\n" ); mThreadVector->deleteElement( i ); delete thread; threadFound = true; // jump out of the for loop, since our // vector size has changed i = numThreads; } } } mLock->unlock(); } } between-6+dfsg1.orig/minorGems/network/SocketClient.h0000640000175000017500000000415411435543335021444 0ustar pabspabs/* * Modification History * * 2001-January-10 Jason Rohrer * Created. * * 2002-October-13 Jason Rohrer * Added support for timeout on connect. * * 2008-September-30 Jason Rohrer * Added support for non-blocking connect. * * 2009-December-23 Jason Rohrer * Added note about manditory outTimedOut flag. */ #include "minorGems/common.h" #ifndef SOCKET_CLIENT_CLASS_INCLUDED #define SOCKET_CLIENT_CLASS_INCLUDED #include "Socket.h" #include "HostAddress.h" #include /** * Class that can make connections to socket servers. * * Note: Implementation for the functions defined here is provided * separately for each platform (in the mac/ linux/ and win32/ * subdirectories). * * @author Jason Rohrer */ class SocketClient { public: /** * Connects to a server and returns a socket. * * NOTE: * If inAddress is not in numerical format (in other words, if it * requires a DNS lookup before connection), this function may block * even if non-blocking mode is specified. * Consider using LookupThread to lookup the address before * calling this function. * * @param inAddress the host to connect to. Must be destroyed * by caller. * @param inTimeoutInMilliseconds the timeout value for the connect * in milliseconds, or -1 for no timeout. Defaults to -1. * Set to 0 for non-blocking connect that returns a not-yet-connected * socket. * @param outTimedOut pointer to where the timeout flag should * be returned, or NULL for no timeout. If timeout used, will * be set to true if timeout happened, or false if it did not. * Defaults to NULL. * MUST pass a pointer here if you want to use time-outs or * non-blocking connects. * * @return a socket for the connection, or NULL if an error occurs. */ static Socket *connectToServer( HostAddress *inAddress, long inTimeoutInMilliseconds = -1, char *outTimedOut = NULL ); }; #endif between-6+dfsg1.orig/minorGems/network/SocketManager.h0000640000175000017500000000324011435543335021573 0ustar pabspabs/* * Modification History * * 2004-December-13 Jason Rohrer * Created. */ #ifndef SOCKET_MANAGER_INCLUDED #define SOCKET_MANAGER_INCLUDED #include "minorGems/network/Socket.h" #include "minorGems/system/MutexLock.h" #include "minorGems/util/SimpleVector.h" /** * Ensures proper destruction of static data items at program termination. */ class SocketManagerDataWrapper { public: SocketManagerDataWrapper(); ~SocketManagerDataWrapper(); MutexLock *mLock; SimpleVector *mSocketVector; }; /** * A class that ensures thread-safe socket shutdown and destruction. * * Useful if a thread needs to break a socket that another thread is using. */ class SocketManager { public: /** * Adds a socket to this manager. * * @param inSocket the socket to add. * Will be destroyed by this manager. */ static void addSocket( Socket *inSocket ); /** * Breaks the connection (both directions) associated with a socket. * * This call is safe even if inSocket has already been destroyed. * * @param inSocket the socket to break. */ static void breakConnection( Socket *inSocket ); /** * Destroys a socket and removes it from this manager. * * @param inSocket the socket to destroy. */ static void destroySocket( Socket *inSocket ); private: // allocated statically to ensure destruction on program termination static SocketManagerDataWrapper mDataWrapper; }; #endif between-6+dfsg1.orig/minorGems/network/SocketManager.cpp0000640000175000017500000000375011435543335022134 0ustar pabspabs/* * Modification History * * 2004-December-13 Jason Rohrer * Created. */ #include "SocketManager.h" // static initialization SocketManagerDataWrapper SocketManager::mDataWrapper; SocketManagerDataWrapper::SocketManagerDataWrapper() : mLock( new MutexLock() ), mSocketVector( new SimpleVector() ) { } SocketManagerDataWrapper::~SocketManagerDataWrapper() { int numSockets = mSocketVector->size(); for( int i=0; igetElement( i ) ); } delete mSocketVector; delete mLock; } void SocketManager::addSocket( Socket *inSocket ) { MutexLock *lock = mDataWrapper.mLock; SimpleVector *socketVector = mDataWrapper.mSocketVector; lock->lock(); socketVector->push_back( inSocket ); lock->unlock(); } void SocketManager::breakConnection( Socket *inSocket ) { MutexLock *lock = mDataWrapper.mLock; SimpleVector *socketVector = mDataWrapper.mSocketVector; lock->lock(); int numSockets = socketVector->size(); char found = false; for( int i=0; igetElement( i ) ); if( currentSocket == inSocket ) { currentSocket->breakConnection(); found = true; } } lock->unlock(); } void SocketManager::destroySocket( Socket *inSocket ) { MutexLock *lock = mDataWrapper.mLock; SimpleVector *socketVector = mDataWrapper.mSocketVector; lock->lock(); int numSockets = socketVector->size(); char found = false; for( int i=0; igetElement( i ) ); if( currentSocket == inSocket ) { delete currentSocket; socketVector->deleteElement( i ); found = true; } } lock->unlock(); } between-6+dfsg1.orig/minorGems/network/SocketUDP.h0000640000175000017500000001325411435543336020660 0ustar pabspabs/* * Modification History * * 2004-November-3 Jason Rohrer * Created. * * 2004-November-4 Jason Rohrer * Added default receive timeout (infinite). * * 2004-November-9 Jason Rohrer * Added functions for comparing and copying UDPAddresses. */ #ifndef SOCKET_UDP_INCLUDED #define SOCKET_UDP_INCLUDED /** * Structure representing a UDP endpoint. */ struct UDPAddress { // binary internet address in network byte order unsigned long mIPAddress; // port number in network byte order unsigned short mPort; }; /** * Network socket that can be used as an endpoint for sending and receiving * UDP packets (unreliable datagrams). * * Note: Implementation for the functions defined here is provided * separately for each platform (in the unix/ and win32/ subdirectories). * * Socket::initSocketFramework() must be called once before this class * is used. * * @author Jason Rohrer */ class SocketUDP { public: /** * Constructs a UDP socket and starts listening for incoming datagrams. * * @param inReceivePort the port to listen on, in platform-dependent * byte order. */ SocketUDP( unsigned short inReceivePort ); ~SocketUDP(); /** * Makes a UDPAddress structure. * * @param inAddress the IP address in ascii numbers-and-dots notation. * Must be destroyed by caller if non-const. * @param inPort the port number in platform-specific byte order. * * @return an address structure, or NULL if converting the address * fails. * Must be destroyed by caller if non-NULL. */ static struct UDPAddress *makeAddress( const char *inAddress, unsigned short inPort ); /** * Extracts address elements from a UDPAddress structure. * * @param inAddress the address structure. Must be destroyed by * caller. * @param outPort pointer to where the port number, in * platform-specific byte order, should be returned. * * @return the IP address in ascci numbers-and-dots notation. * Must be destroyed by caller. */ static char *extractAddress( struct UDPAddress *inAddress, unsigned short *outPort ); /** * Compares two UDP addresses. * * @param inFirst the first address. * @param inSecond the second address. * * @return true if the addresses are equal, or false if they are * different. */ static char compare( struct UDPAddress *inFirst, struct UDPAddress *inSecond ); /** * Makes a copy of a UDP address. * * @param inAddress the address to copy. * * @return a copy of the address. Must be destroyed by caller. */ static struct UDPAddress *copy( struct UDPAddress *inAddress ); /** * Sends a datagram through this socket. * * Note: the recommended maximum data length is 512 bytes * to ensure that the datagram can be routed without * fragmentation through all spec-compliant routers. * Most routers support larger datagrams, however. * * @param inAddress the address to send data through. Must be * destroyed by caller. * @param inData the data bytes to send. * @param inNumBytes the number of bytes to send. * * @return the number of bytes sent successfully, * or -1 for a socket error. */ int send( struct UDPAddress *inAddress, unsigned char *inData, unsigned long inNumBytes ); /** * Receives a datagram from this socket. * * @param outAddress pointer to where the address of the remote * host (the datagram sender) should be returned. * Will be set to NULL on socket error or timeout. * Must be destroyed by caller if non-NULL. * @param outData pointer to where the received data should be * returned. Will be set to NULL on socket error or timeout. * Must be destroyed by caller if non-NULL. * @param inTimeout the timeout for this receive operation in * milliseconds. Set to -1 for an infinite timeout. * -2 is returned from this call in the event of a timeout. * Defaults to -1. * * @return the number of bytes received successfully, * -1 for a socket error, or -2 for a timeout. */ int receive( struct UDPAddress **outAddress, unsigned char **outData, long inTimeout = -1 ); /** * Used by platform-specific implementations. */ void *mNativeObjectPointer; }; inline char SocketUDP::compare( struct UDPAddress *inFirst, struct UDPAddress *inSecond ) { if( inFirst->mIPAddress == inSecond->mIPAddress && inFirst->mPort == inSecond->mPort ) { return true; } else { return false; } } inline struct UDPAddress *SocketUDP::copy( struct UDPAddress *inAddress ) { struct UDPAddress *returnAddress = new struct UDPAddress; returnAddress->mIPAddress = inAddress->mIPAddress; returnAddress->mPort = inAddress->mPort; return returnAddress; } #endif between-6+dfsg1.orig/minorGems/network/socketTest.cpp0000640000175000017500000000426211435543336021541 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. * * 2001-January-28 Jason Rohrer * Added more output. * Added better error checking. * * 2001-December-14 Jason Rohrer * Added a test of HostAddress::getLocalAddress(). * * 2002-July-30 Jason Rohrer * Added a test of streams. * * 2002-July-31 Jason Rohrer * Changed to test multiple blocks. * * 2002-February-4 Jason Rohrer * Added test of getting local address from socket. */ #include "Socket.h" #include "SocketStream.h" #include "SocketServer.h" #include "SocketClient.h" #include "HostAddress.h" #include int main() { HostAddress *address = HostAddress::getLocalAddress(); printf( "Local address: " ); address->print(); printf( "\n" ); int port = 5158; SocketServer *server = new SocketServer( port, 100 ); printf( "Waiting for a connection on port %d\n", port ); Socket *receiveSocket = server->acceptConnection(); if( receiveSocket == NULL ) { return 1; } printf( "Connection received\n" ); HostAddress *localAddress = receiveSocket->getLocalHostAddress(); if( localAddress != NULL ) { printf( "Our local address (fetched from socket) is " ); localAddress->print(); printf( "\n" ); delete localAddress; } SocketStream *receiveStream = new SocketStream( receiveSocket ); receiveStream->setReadTimeout( 10000 ); int numBytes = 4000; int checksum = 0; unsigned char *buffer = new unsigned char[numBytes]; /* for( int i=0; iread( buffer, 1 ); checksum += buffer[ 0 ]; if( numRec != 1) { printf( "Faiedl to read.\n" ); return 1; } //sleep( 1 ); } */ int count = 0; while( true ) { int numRec = receiveStream->read( buffer, numBytes ); printf( "Received %d successfully,\tcount = %d\n", numBytes, count ); count++; } /* for( int i=0; icopy() ), mNumericalAddress( NULL ), mLookupDone( false ) { start(); } LookupThread::~LookupThread() { join(); delete mAddress; if( mNumericalAddress != NULL ) { delete mNumericalAddress; } } char LookupThread::isLookupDone() { mLock.lock(); char done = mLookupDone; mLock.unlock(); return done; } HostAddress *LookupThread::getResult() { mLock.lock(); HostAddress *result = NULL; if( mNumericalAddress != NULL ) { result = mNumericalAddress->copy(); } mLock.unlock(); return result; } void LookupThread::run() { HostAddress *numAddress = mAddress->getNumericalAddress(); mLock.lock(); mLookupDone = true; mNumericalAddress = numAddress; mLock.unlock(); setFinished(); } between-6+dfsg1.orig/minorGems/network/p2pParts/0000750000175000017500000000000011435543336020413 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/network/p2pParts/MultiSourceDownloader.h0000640000175000017500000000546211435543336025066 0ustar pabspabs/* * Modification History * * 2004-November-21 Jason Rohrer * Created. * * 2004-November-23 Jason Rohrer * Fixed compile errors caused by multiple definitions. */ #ifndef MULTISOURCE_DOWNLOADER_INCLUDED #define MULTISOURCE_DOWNLOADER_INCLUDED /** * Abstract API for multi-source downloads. * * @author Jason Rohrer. */ extern int MULTISOURCE_DOWNLOAD_IN_PROGRESS; extern int MULTISOURCE_DOWNLOAD_FAILED; extern int MULTISOURCE_DOWNLOAD_CANCELED; /** * Gets a file from multiple sources. * * @param inFileDescriptor abstract pointer to a file descriptor that can * be used by inChunkGetter to identify a file. * Must be destroyed by caller. * @param inFileSize the size of the file in bytes. * @param inChunkSize the size of a download chunk in bytes. * @param inNumSources the number of file sources. * @param inFileSources an array of abstract pointers to file sources that * can be used by inChunkSize to connect to sources. * Array and elements must be destroyed by caller. * @param inChunkGetter pointer to the function that can be used to get a * chunk. * The function must return an array of chunk bytes (or NULL on failure) * and take the following arguments: * ( void *inFileSource, void *inFileDescriptor, * unsigned long inChunkNumber, unsigned long inChunkSize ). * @praram inDownloadProgressHandler pointer to the handler function for * download progress events. * This function must return true to continue the download (or false * to cancel) and take the following arguments: * (int inResultCode, unsigned long inTotalBytesReceived, * void *inExtraArgument ). * inResultCode will be set to one of MULTISOURCE_DOWNLOAD_IN_PROGRESS, * MULTISOURCE_DOWNLOAD_FAILED, or MULTISOURCE_DOWNLOAD_CANCELED. * Once a FAILED or CANCELED result code is passed to the handler, the * handler will never be called again, so it should destroy its extra * argument, if necessary. * @param inProgressHandlerExtraArgument pointer to an extra argument to be * passed in to the handler function each time it is called. * Must be destroyed by caller. * @param inDestinationPath the path to save the file to. * Must be destroyed by caller. */ void multiSourceGetFile( void *inFileDescriptor, unsigned long inFileSize, unsigned long inChunkSize, int inNumSources, void **inFileSources, unsigned char * (*inChunkGetter)( void *, void *, unsigned long, unsigned long ), char (*inDownloadProgressHandler)( int, unsigned long, void * ), void *inProgressHandlerExtraArgument, char *inDestinationPath ); #endif between-6+dfsg1.orig/minorGems/network/p2pParts/DuplicateMessageDetector.cpp0000640000175000017500000000464311435543336026040 0ustar pabspabs/* * Modification History * * 2003-August-7 Jason Rohrer * Created. * * 2003-August-14 Jason Rohrer * Changed to output message history to file. */ #include "DuplicateMessageDetector.h" #include "minorGems/util/stringUtils.h" #include #include DuplicateMessageDetector::DuplicateMessageDetector( int inMessageHistorySize ) : mMaxHistorySize( inMessageHistorySize ), mLock( new MutexLock() ), mSeenIDs( new SimpleVector() ), mTotalMessageCount( 0 ), mHistoryOutputFile( NULL ) { mHistoryOutputFile = fopen( "messageHistory.log", "w" ); } DuplicateMessageDetector::~DuplicateMessageDetector() { int numIDs = mSeenIDs->size(); for( int i=0; igetElement( i ) ); } delete mSeenIDs; delete mLock; fclose( mHistoryOutputFile ); } char DuplicateMessageDetector::checkIfMessageSeen( char *inMessageUniqueID ) { mLock->lock(); mTotalMessageCount++; int numIDs = mSeenIDs->size(); char matchSeen = false; for( int i=0; igetElement( i ) ); if( strcmp( otherID, inMessageUniqueID ) == 0 ) { // match // push the ID back to the end of the queue mSeenIDs->deleteElement( i ); mSeenIDs->push_back( otherID ); matchSeen = true; } } if( mHistoryOutputFile != NULL ) { fprintf( mHistoryOutputFile, "%d %d %s", mTotalMessageCount, (int)( time( NULL ) ), inMessageUniqueID ); } if( !matchSeen ) { // add the message mSeenIDs->push_back( stringDuplicate( inMessageUniqueID ) ); // make sure history not too long if( mSeenIDs->size() > mMaxHistorySize ) { delete [] *( mSeenIDs->getElement( 0 ) ); mSeenIDs->deleteElement( 0 ); } if( mHistoryOutputFile != NULL ) { fprintf( mHistoryOutputFile, "\n" ); } } else { // add duplicate tag if( mHistoryOutputFile != NULL ) { fprintf( mHistoryOutputFile, " D\n" ); } } if( mHistoryOutputFile != NULL ) { fflush( mHistoryOutputFile ); } mLock->unlock(); return matchSeen; } between-6+dfsg1.orig/minorGems/network/p2pParts/protocolUtils.h0000640000175000017500000000370111435543336023450 0ustar pabspabs/* * Modification History * * 2003-August-12 Jason Rohrer * Created. * * 2003-August-22 Jason Rohrer * Added function for getting a token after reading. */ #ifndef P2P_PROTOCOL_UTILS_INCLUDED #define P2P_PROTOCOL_UTILS_INCLUDED #include "minorGems/io/InputStream.h" #include "minorGems/io/OutputStream.h" /** * A collection of common protocol processing functions. * * @author Jason Rohrer */ /** * Reads from a stream up to (and including) the * first occurence of a tag. * * @param inInputStream the stream to read from. * Must be destroyed by caller. * @param inTag the tag to look for. * Must be destroyed by caller if non-const. * @param inMaxCharsToRead the maximum number of characters to read. * * @return the read string, or NULL if reading fails. * NULL is also returned if the character count limit is * reached. * Must be destroyed by caller if non-NULL. */ char *readStreamUpToTag( InputStream *inInputStream, char *inTag, int inMaxCharsToRead ); /** * Reads from a stream up to (and including) the * first occurence of a tag and gets a specific token from the read data. * * Tokens are split by whitespace. * * @param inInputStream the stream to read from. * Must be destroyed by caller. * @param inTag the tag to look for. * Must be destroyed by caller if non-const. * @param inMaxCharsToRead the maximum number of characters to read. * @param inTokenNumber the token to get after reading up to inTag and * tokenizing the read data. 0 specifies the first token. * * @return the read token string, or NULL if reading or token extraction fails. * NULL is also returned if the character count limit is * reached. * Must be destroyed by caller if non-NULL. */ char *readStreamUpToTagAndGetToken( InputStream *inInputStream, char *inTag, int inMaxCharsToRead, int inTokenNumber ); #endif between-6+dfsg1.orig/minorGems/network/p2pParts/MultipleConnectionPreventer.cpp0000640000175000017500000000333311435543336026630 0ustar pabspabs/* * Modification History * * 2003-June-20 Jason Rohrer * Created. */ #include "MultipleConnectionPreventer.h" MultipleConnectionPreventer::MultipleConnectionPreventer() : mLock( new MutexLock() ), mConnections( new SimpleVector() ) { } MultipleConnectionPreventer::~MultipleConnectionPreventer() { mLock->lock(); int numConnections = mConnections->size(); for( int i=0; igetElement( i ) ); } delete mConnections; mLock->unlock(); delete mLock; } char MultipleConnectionPreventer::addConnection( HostAddress *inAddress ) { mLock->lock(); char connectionExists = false; int numConnections = mConnections->size(); for( int i=0; igetElement( i ) ); if( inAddress->equals( otherConnection ) ) { connectionExists = true; } } if( !connectionExists ) { mConnections->push_back( inAddress->copy() ); } mLock->unlock(); return !connectionExists; } void MultipleConnectionPreventer::connectionBroken( HostAddress *inAddress ) { mLock->lock(); char connectionFound = false; int numConnections = mConnections->size(); for( int i=0; igetElement( i ) ); if( inAddress->equals( otherConnection ) ) { connectionFound = true; delete otherConnection; mConnections->deleteElement( i ); } } mLock->unlock(); } between-6+dfsg1.orig/minorGems/network/p2pParts/MessagePerSecondLimiter.h0000640000175000017500000000402311435543336025301 0ustar pabspabs/* * Modification History * * 2003-October-9 Jason Rohrer * Created. * * 2003-October-12 Jason Rohrer * Switched to a floating point limit. * * 2004-January-2 Jason Rohrer * Added seprate mutex for transmission function to prevent UI freeze. */ #ifndef MESSAGE_PER_SECOND_LIMITER_INCLUDED_H #define MESSAGE_PER_SECOND_LIMITER_INCLUDED_H #include "minorGems/system/MutexLock.h" /** * Class that limits the number of messages transmitted per second. * * @author Jason Rohrer */ class MessagePerSecondLimiter { public: /** * Constructs a limiter. * * @param inLimitPerSecond the maximum number of messages * transmitted per second, or -1 for no limit. * Defaults to -1. */ MessagePerSecondLimiter( double inLimitPerSecond = -1 ); ~MessagePerSecondLimiter(); /** * Sets the limit. * * Thread safe. * * @param inLimitPerSecond the maximum number of messages * transmitted per second, or -1 for no limit. */ void setLimit( double inLimitPerSecond ); /** * Gets the limit. * * Thread safe. * * @return the maximum number of messages * transmitted per second, or -1 if no limit set. */ double getLimit(); /** * Called by a message transmitter to indicate that a message * is about to be transmitted. Will block if messages * are being transmitted too frequently. * * Thread safe. */ void messageTransmitted(); protected: MutexLock *mLock; MutexLock *mTransmitLock; double mLimitPerSecond; unsigned long mMillisecondsBetweenMessages; unsigned long mSecondTimeOfLastMessage; unsigned long mMillisecondTimeOfLastMessage; }; #endif between-6+dfsg1.orig/minorGems/network/p2pParts/DuplicateMessageDetector.h0000640000175000017500000000272511435543336025504 0ustar pabspabs/* * Modification History * * 2003-August-7 Jason Rohrer * Created. * * 2003-August-14 Jason Rohrer * Changed to output message history to file. */ #ifndef DUPLICATE_MESSAGE_DETECTOR_INCLUDED_H #define DUPLICATE_MESSAGE_DETECTOR_INCLUDED_H #include "minorGems/system/MutexLock.h" #include "minorGems/util/SimpleVector.h" #include /** * Class that detects duplicates of past messages so that they can be * discarded. * * @author Jason Rohrer */ class DuplicateMessageDetector { public: /** * Constructs a detector. * * @param inMessageHistorySize the number of message IDs to * maintain in our history. * Defaults to 1000. */ DuplicateMessageDetector( int inMessageHistorySize = 1000 ); ~DuplicateMessageDetector(); /** * Checks if a message has been seen in the past. * * @param inMessageUniqueID the unique ID for the message. * Must be destroyed by caller. * * @return true if the message has already been seen, or * false if the message is new. */ char checkIfMessageSeen( char *inMessageUniqueID ); protected: int mMaxHistorySize; MutexLock *mLock; SimpleVector *mSeenIDs; int mTotalMessageCount; FILE *mHistoryOutputFile; }; #endif between-6+dfsg1.orig/minorGems/network/p2pParts/MessagePerSecondLimiter.cpp0000640000175000017500000000523111435543336025636 0ustar pabspabs/* * Modification History * * 2003-October-9 Jason Rohrer * Created. * * 2003-October-12 Jason Rohrer * Switched to a floating point limit. * * 2004-January-2 Jason Rohrer * Added seprate mutex for transmission function to prevent UI freeze. * * 2005-April-15 Jason Rohrer * Changed to use updated Thread interface. */ #include "MessagePerSecondLimiter.h" #include "minorGems/system/Time.h" #include "minorGems/system/Thread.h" MessagePerSecondLimiter::MessagePerSecondLimiter( double inLimitPerSecond ) : mLock( new MutexLock() ), mTransmitLock( new MutexLock() ), mLimitPerSecond( inLimitPerSecond ) { if( mLimitPerSecond != -1 ) { mMillisecondsBetweenMessages = (int)( 1000 / mLimitPerSecond ); } else { mMillisecondsBetweenMessages = 0; } Time::getCurrentTime( &mSecondTimeOfLastMessage, &mMillisecondTimeOfLastMessage ); } MessagePerSecondLimiter::~MessagePerSecondLimiter() { delete mLock; delete mTransmitLock; } void MessagePerSecondLimiter::setLimit( double inLimitPerSecond ) { mLock->lock(); mLimitPerSecond = inLimitPerSecond; if( mLimitPerSecond != -1 ) { mMillisecondsBetweenMessages = (int)( 1000 / mLimitPerSecond ); } else { mMillisecondsBetweenMessages = 0; } mLock->unlock(); } double MessagePerSecondLimiter::getLimit() { mLock->lock(); double limit = mLimitPerSecond; mLock->unlock(); return limit; } void MessagePerSecondLimiter::messageTransmitted() { // allow only one transmitter to report at a time mTransmitLock->lock(); // protect our variables (make sure settings functions are not // called while we touch the variables) mLock->lock(); unsigned long millisecondsSinceLastMessage = Time::getMillisecondsSince( mSecondTimeOfLastMessage, mMillisecondTimeOfLastMessage ); if( millisecondsSinceLastMessage < mMillisecondsBetweenMessages ) { // this message is coming too soon after last message // sleep unsigned long sleepTime = mMillisecondsBetweenMessages - millisecondsSinceLastMessage; // unlock main lock befor sleeping so that settings can be changed mLock->unlock(); Thread::staticSleep( sleepTime ); // relock mLock->lock(); } Time::getCurrentTime( &mSecondTimeOfLastMessage, &mMillisecondTimeOfLastMessage ); mLock->unlock(); mTransmitLock->unlock(); } between-6+dfsg1.orig/minorGems/network/p2pParts/OutboundChannel.h0000640000175000017500000001150611435543336023660 0ustar pabspabs/* * Modification History * * 2003-June-22 Jason Rohrer * Copied from the konspire2b project and modified. * * 2003-July-27 Jason Rohrer * Added a setHost function. * * 2003-September-23 Jason Rohrer * Replaced sleep-waiting with semaphores. This results in a major speedup. * * 2003-October-9 Jason Rohrer * Added support for message limiters. * * 2004-December-12 Jason Rohrer * Added a queue size parameter. */ #ifndef OUTBOUND_CHANNEL_INCLUDED #define OUTBOUND_CHANNEL_INCLUDED #include "minorGems/network/HostAddress.h" #include "minorGems/io/OutputStream.h" #include "minorGems/system/MutexLock.h" #include "minorGems/system/Semaphore.h" #include "minorGems/system/Thread.h" #include "minorGems/util/SimpleVector.h" #include "minorGems/network/p2pParts/MessagePerSecondLimiter.h" /** * A channel that can send messages to a receiving host. * * NOTE: * None of the member functions are safe to call if this class has been * destroyed. Since the application-specific channel manager class can * destroy a given instance of this class at any time, these member functions * should NEVER be called directly. * Instead, the appropriate channel manager functions should be called. * * @author Jason Rohrer */ class OutboundChannel : public Thread { public: /** * Constructs an OutboundChannel and starts the sending thread. * * @param inOutputStream the stream wrapped by this channel. * Must be destroyed by caller. * @param inHost the host on the other end of this channel. * Will be destroyed when this class is destroyed. * @param inLimiter the limiter for outbound messages. * Must be destroyed by caller after this class is destroyed. * @param inQueueSize the size of the send queue. Defaults to 50. */ OutboundChannel( OutputStream *inOutputStream, HostAddress *inHost, MessagePerSecondLimiter *inLimiter, unsigned long inQueueSize = 50 ); /** * Stops the sending thread and destroys this channel. */ ~OutboundChannel(); /** * Sends a message to this channel's receiver. * * Thread safe. * * This call queues the message to be sent, so it returns before * the send is complete. * * @param inMessage the message to send. * Must be destroyed by caller if non-const. * @param inPriority the priority of this message. * Values less than or equal to 0 indicate default priority, * while positive values suggest higher priority. * Granularity of prioritization is implementation dependent. * Defaults to 0. * * @return true if the channel is still functioning properly, * or false if the channel has been broken. */ char sendMessage( char *inMessage, int inPriority = 0 ); /** * Gets the host receiving from this channel. * * @return this channel's receiving host. * Must be destroyed by caller. */ HostAddress * getHost( ); /** * Sets the address of the remotely connected host. * * @param inHost the host on the other end of this channel. * Will be destroyed when this class is destroyed. */ void setHost( HostAddress *inHost ); /** * Gets the number of outbound messages that have been sent on * this channel. * * Thread safe. * * @return the number of sent messages. */ int getSentMessageCount(); /** * Gets the number of outbound messages that are currently * queued for this channel. * * Thread safe. * * @return the number of queued messages. */ int getQueuedMessageCount(); /** * Gets the number of outbound messages that have been dropped * by this channel. * * Thread safe. * * @return the number of dropped messages. */ int getDroppedMessageCount(); // implements the Thread interface void run(); protected: MutexLock *mLock; Semaphore *mMessageReadySemaphore; OutputStream *mStream; HostAddress *mHost; MessagePerSecondLimiter *mLimiter; char mConnectionBroken; char mThreadStopped; SimpleVector *mMessageQueue; SimpleVector *mHighPriorityMessageQueue; int mMaxQueueSize; int mDroppedMessageCount; int mSentMessageCount; }; #endif between-6+dfsg1.orig/minorGems/network/p2pParts/MultipleConnectionPreventer.h0000640000175000017500000000305011435543336026271 0ustar pabspabs/* * Modification History * * 2003-June-20 Jason Rohrer * Created. */ #ifndef MULTIPLE_CONNECTION_PREVENTER_INCLUDED_H #define MULTIPLE_CONNECTION_PREVENTER_INCLUDED_H #include "minorGems/system/MutexLock.h" #include "minorGems/util/SimpleVector.h" #include "minorGems/network/HostAddress.h" /** * Class that tracks current connections of a p2p node and prevents * multiple connections to the same address. * * @author Jason Rohrer */ class MultipleConnectionPreventer { public: MultipleConnectionPreventer(); ~MultipleConnectionPreventer(); /** * Adds a connection to a host, and checks if the connection * is permitted. * * The connection will not be permitted if another connection * to the address already exists. * * Thread safe. * * @param inAddress the address of the connection. * Must be destroyed by caller. * * @return true if the connection is permitted, or false otherwise. */ char addConnection( HostAddress *inAddress ); /** * Reports that a connection has been broken. * * Thread safe. * * @param inAddress the address of the broken connection. * Must be destroyed by caller. */ void connectionBroken( HostAddress *inAddress ); protected: MutexLock *mLock; SimpleVector *mConnections; }; #endif between-6+dfsg1.orig/minorGems/network/p2pParts/OutboundChannel.cpp0000640000175000017500000001363411435543336024217 0ustar pabspabs/* * Modification History * * 2003-June-22 Jason Rohrer * Copied from the konspire2b project and modified. * * 2003-July-27 Jason Rohrer * Added a setHost function. * * 2003-September-23 Jason Rohrer * Replaced sleep-waiting with semaphores. This results in a major speedup. * * 2003-October-9 Jason Rohrer * Added support for message limiters. * * 2004-January-11 Jason Rohrer * Made include paths explicit to help certain compilers. * * 2004-December-12 Jason Rohrer * Added a queue size parameter. */ #include "minorGems/network/p2pParts/OutboundChannel.h" OutboundChannel::OutboundChannel( OutputStream *inOutputStream, HostAddress *inHost, MessagePerSecondLimiter *inLimiter, unsigned long inQueueSize ) : mLock( new MutexLock() ), mMessageReadySemaphore( new Semaphore() ), mStream( inOutputStream ), mHost( inHost ), mLimiter( inLimiter ), mConnectionBroken( false ), mThreadStopped( false ), mMessageQueue( new SimpleVector() ), mHighPriorityMessageQueue( new SimpleVector() ), mMaxQueueSize( inQueueSize ), mDroppedMessageCount( 0 ), mSentMessageCount( 0 ) { // start our thread start(); } OutboundChannel::~OutboundChannel() { mLock->lock(); mThreadStopped = true; mLock->unlock(); // wake the thread up if it is waiting mMessageReadySemaphore->signal(); // wait for our thread to get the stop signal and finish join(); mLock->lock(); delete mMessageReadySemaphore; // clear the queues int numMessages = mMessageQueue->size(); int i; for( i=0; igetElement( i ) ); delete [] message; } delete mMessageQueue; numMessages = mHighPriorityMessageQueue->size(); for( i=0; igetElement( i ) ); delete [] message; } delete mHighPriorityMessageQueue; delete mHost; mLock->unlock(); delete mLock; } char OutboundChannel::sendMessage( char * inMessage, int inPriority ) { mLock->lock(); char sent; if( !mConnectionBroken ) { // add it to the queue SimpleVector *queueToUse; if( inPriority <=0 ) { queueToUse = mMessageQueue; } else { queueToUse = mHighPriorityMessageQueue; } queueToUse->push_back( stringDuplicate( inMessage ) ); sent = true; if( queueToUse->size() > mMaxQueueSize ) { // the queue is over-full // drop the oldest message char *message = *( queueToUse->getElement( 0 ) ); queueToUse->deleteElement( 0 ); delete [] message; mDroppedMessageCount++; } } else { // channel no longer working sent = false; } mLock->unlock(); if( sent ) { mMessageReadySemaphore->signal(); } return sent; } HostAddress * OutboundChannel::getHost() { return mHost->copy(); } void OutboundChannel::setHost( HostAddress *inHost ) { delete mHost; mHost = inHost->copy(); } int OutboundChannel::getSentMessageCount() { mLock->lock(); int count = mSentMessageCount; mLock->unlock(); return count; } int OutboundChannel::getQueuedMessageCount() { mLock->lock(); int count = mMessageQueue->size() + mHighPriorityMessageQueue->size(); mLock->unlock(); return count; } int OutboundChannel::getDroppedMessageCount() { mLock->lock(); int count = mDroppedMessageCount; mLock->unlock(); return count; } void OutboundChannel::run() { mLock->lock(); char stopped = mThreadStopped; mLock->unlock(); while( !stopped ) { // get a message from the queue, checking high priority queue first char *message = NULL; mLock->lock(); if( mHighPriorityMessageQueue->size() >= 1 ) { message = *( mHighPriorityMessageQueue->getElement( 0 ) ); mHighPriorityMessageQueue->deleteElement( 0 ); } else if( mMessageQueue->size() >= 1 ) { message = *( mMessageQueue->getElement( 0 ) ); mMessageQueue->deleteElement( 0 ); } mLock->unlock(); // note that we're unlocked during the send, so messages // can be freely added to the queue without blocking while we send // this message if( message != NULL ) { // obey the limit // we will block here if message rate is too high mLimiter->messageTransmitted(); int bytesSent = mStream->writeString( message ); int messageLength = strlen( message ); delete [] message; char sent; if( bytesSent == messageLength ) { sent = true; mLock->lock(); mSentMessageCount++; mLock->unlock(); } else { sent = false; } if( !sent ) { // connection is broken // stop this thread mLock->lock(); mConnectionBroken = true; mThreadStopped = true; mLock->unlock(); } } else { // no messages in the queue. // wait for more messages to be ready mMessageReadySemaphore->wait(); } // check if we've been stopped mLock->lock(); stopped = mThreadStopped; mLock->unlock(); } } between-6+dfsg1.orig/minorGems/network/p2pParts/HostCatcher.cpp0000640000175000017500000001516011435543336023332 0ustar pabspabs/* * Modification History * * 2003-June-22 Jason Rohrer * Copied from the konspire2b project and modified. * * 2003-July-27 Jason Rohrer * Fixed a bug when catcher is empty. * * 2003-December-21 Jason Rohrer * Fixed a memory leak when catcher is full. * * 2004-January-11 Jason Rohrer * Made include paths explicit to help certain compilers. * * 2004-December-20 Jason Rohrer * Changed to convert to numerical form before comparing against host list. * Changed getHost to return hosts in random order. * Added a getOrderedHost function that returns hosts in linear order. */ #include "minorGems/network/p2pParts/HostCatcher.h" #include "minorGems/util/stringUtils.h" #include "minorGems/util/random/StdRandomSource.h" HostCatcher::HostCatcher( int inMaxListSize ) : mMaxListSize( inMaxListSize ), mHostVector( new SimpleVector() ), mLock( new MutexLock() ), mRandSource( new StdRandomSource() ) { } HostCatcher::~HostCatcher() { mLock->lock(); int numHosts = mHostVector->size(); for( int i=0; igetElement( i ) ); } delete mHostVector; mLock->unlock(); delete mLock; delete mRandSource; } void HostCatcher::addHost( HostAddress * inHost ) { // convert to numerical form once and for all here // (to avoid converting over and over in equals checks below) HostAddress *numericalAddress = inHost->getNumericalAddress(); if( numericalAddress != NULL ) { mLock->lock(); // make sure this host doesn't already exist in our list char exists = false; int numHosts = mHostVector->size(); for( int i=0; igetElement( i ) ); if( otherHost->equals( numericalAddress ) ) { exists = true; // jump out of loop i = numHosts; } } if( !exists ) { mHostVector->push_back( numericalAddress->copy() ); } while( mHostVector->size() > mMaxListSize ) { // remove first host from queue HostAddress *host = *( mHostVector->getElement( 0 ) ); mHostVector->deleteElement( 0 ); delete host; } mLock->unlock(); delete numericalAddress; } } HostAddress * HostCatcher::getHostOrdered( ) { mLock->lock(); int numHosts = mHostVector->size(); if( numHosts == 0 ) { mLock->unlock(); return NULL; } // remove first host from queue HostAddress *host = *( mHostVector->getElement( 0 ) ); mHostVector->deleteElement( 0 ); // add host to end of queue mHostVector->push_back( host ); HostAddress *hostCopy = host->copy(); mLock->unlock(); return hostCopy; } HostAddress * HostCatcher::getHost( ) { mLock->lock(); int numHosts = mHostVector->size(); if( numHosts == 0 ) { mLock->unlock(); return NULL; } // remove random host from queue int index = mRandSource->getRandomBoundedInt( 0, numHosts - 1 ); HostAddress *host = *( mHostVector->getElement( index ) ); mHostVector->deleteElement( index ); // add host to end of queue mHostVector->push_back( host ); HostAddress *hostCopy = host->copy(); mLock->unlock(); return hostCopy; } SimpleVector *HostCatcher::getHostList( int inMaxHostCount, HostAddress *inSkipHost ) { HostAddress *hostToSkip; if( inSkipHost != NULL ) { hostToSkip = inSkipHost->copy(); } else { // don't skip any host // create a dummy host that won't match any other valid hosts // make sure dummy is in numerical form to avoid DNS lookups hostToSkip = new HostAddress( stringDuplicate( "1.1.1.1" ), 1 ); } SimpleVector *collectedHosts = new SimpleVector(); char repeat = false; int numCollected = 0; // This function assumes that getHostOrdered() draws // hosts in order with no repetition except when we have // exhausted the host supply. // Note that this will not be true when other threads // have getHostOrdered() (or getHost) calls interleaved with ours, but this // should be a rare case. It will simply result // in a smaller host list being returned. HostAddress *firstHost = getHostOrdered(); if( firstHost == NULL ) { // the catcher is empty delete hostToSkip; // an empty host list return collectedHosts; } if( ! hostToSkip->equals( firstHost ) ) { collectedHosts->push_back( firstHost ); numCollected++; } while( numCollected < inMaxHostCount && !repeat ) { HostAddress *nextHost = getHostOrdered(); if( nextHost->equals( firstHost ) ) { delete nextHost; repeat = true; } else { if( ! hostToSkip->equals( nextHost ) ) { collectedHosts->push_back( nextHost ); numCollected++; } else { delete nextHost; } } } if( hostToSkip->equals( firstHost ) ) { // we didn't include firstHost in our collectedHosts, so // we must delete it. delete firstHost; } delete hostToSkip; return collectedHosts; } void HostCatcher::addHostList( SimpleVector * inHostList ) { int numToAdd = inHostList->size(); for( int i=0; igetElement( i ) ) ); } } void HostCatcher::noteHostBad( HostAddress * inHost ) { mLock->lock(); // make sure this host already exists in our list char exists = false; HostAddress *foundHost = NULL; int numHosts = mHostVector->size(); for( int i=0; igetElement( i ) ); if( otherHost->equals( inHost ) ) { exists = true; // delete the host that we've found mHostVector->deleteElement( i ); foundHost = otherHost; // jump out of loop i = numHosts; } } if( exists ) { delete foundHost; //mHostVector->push_back( foundHost ); } mLock->unlock(); } between-6+dfsg1.orig/minorGems/network/p2pParts/HostCatcher.h0000640000175000017500000000730211435543336022776 0ustar pabspabs/* * Modification History * * 2003-June-22 Jason Rohrer * Copied from the konspire2b project and modified. * * 2004-December-20 Jason Rohrer * Changed getHost to return hosts in random order. * Added a getOrderedHost function that returns hosts in linear order. */ #ifndef HOST_CATCHER_INCLUDED #define HOST_CATCHER_INCLUDED #include "minorGems/network/HostAddress.h" #include "minorGems/util/SimpleVector.h" #include "minorGems/util/random/RandomSource.h" #include "minorGems/system/MutexLock.h" /** * Manages a collection of hosts. * * @author Jason Rohrer */ class HostCatcher { public: /** * Constructs a host catcher. * * @param inMaxListSize the maximum number of hosts to hold. */ HostCatcher( int inMaxListSize ); ~HostCatcher(); /** * Adds a host to this catcher. * * Thread safe. * * @param inHost the host to add. * Must be destroyed by caller. */ void addHost( HostAddress * inHost ); /** * Gets a "fresh" host from this catcher. * * The returned host is "fresh" in that it has not * been returned by this call in a while. * * Thread safe. * * @return a host, or NULL if there are no hosts. * Must be destroyed by caller if non-NULL. */ HostAddress * getHost( ); /** * Gets a "fresh" host list from this catcher. * The result of this function call is similar to that obtained * by calling getHost inMaxHostCount times and constructing * a HostList from the result, except that this function * will produce a list with no repeated hosts. * * Thread safe. * * @para inMaxHostCount the maximum number of hosts to retrieve. * @param inSkipHost a host to skip when building the list, * or NULL to not skip any host. (Useful * fo constructing a host list at the request of another host.) * Defaults to NULL. Must be destroyed by caller. * * @return a host list containing <= inMaxHostCount hosts. * Vector and addresses must be destroyed by caller. */ SimpleVector *getHostList( int inMaxHostCount, HostAddress *inSkipHost = NULL ); /** * Adds an entire list of hosts to this catcher. * * Thread safe. * * @param inHostList the list to add. * Vector and addresses must be destroyed by caller. */ void addHostList( SimpleVector *inHostList ); /** * Tells this catcher that a host is "bad" * (in other words, dead, dropping connections, etc.). * * Thread safe. * * @param inHost the bad host. * Must be destroyed by caller. */ void noteHostBad( HostAddress * inHost ); protected: int mMaxListSize; SimpleVector *mHostVector; MutexLock *mLock; RandomSource *mRandSource; /** * Gets a "fresh" host from this catcher, walking through the host * list in order. * * The returned host is "fresh" in that it has not * been returned by this call in a while. * * Thread safe. * * @return a host, or NULL if there are no hosts. * Must be destroyed by caller if non-NULL. */ HostAddress *getHostOrdered(); }; #endif between-6+dfsg1.orig/minorGems/network/p2pParts/MultiSourceDownloader.cpp0000640000175000017500000000764711435543336025430 0ustar pabspabs/* * Modification History * * 2004-November-21 Jason Rohrer * Created. * * 2004-November-23 Jason Rohrer * Fixed compile errors caused by multiple definitions. * * 2004-December-4 Jason Rohrer * Fixed bug in source indexing. */ #include "MultiSourceDownloader.h" #include int MULTISOURCE_DOWNLOAD_IN_PROGRESS = 0; int MULTISOURCE_DOWNLOAD_FAILED = 1; int MULTISOURCE_DOWNLOAD_CANCELED = 2; void multiSourceGetFile( void *inFileDescriptor, unsigned long inFileSize, unsigned long inChunkSize, int inNumSources, void **inFileSources, unsigned char * (*inChunkGetter)( void *, void *, unsigned long, unsigned long ), char (*inDownloadProgressHandler)( int, unsigned long, void * ), void *inProgressHandlerExtraArgument, char *inDestinationPath ) { FILE *outputFile = fopen( inDestinationPath, "wb" ); if( outputFile == NULL ) { inDownloadProgressHandler( MULTISOURCE_DOWNLOAD_FAILED, 0, inProgressHandlerExtraArgument ); return; } // for now, just fetch chunks in linear order, using each file source // until it fails char failed = false; char canceled = false; unsigned long chunksSoFar = 0; unsigned long numChunks = inFileSize / inChunkSize; if( inFileSize % inChunkSize != 0 ) { // extra partial chunk numChunks++; } unsigned long bytesSoFar = 0; int sourceIndex = 0; while( sourceIndex < inNumSources && !failed && !canceled && chunksSoFar < numChunks ) { void *source = inFileSources[ sourceIndex ]; unsigned long chunkSize = inChunkSize; if( chunksSoFar * inChunkSize + chunkSize > inFileSize ) { // partial chunk chunkSize = inFileSize - chunksSoFar * inChunkSize; } unsigned char *chunkData = inChunkGetter( source, inFileDescriptor, chunksSoFar, chunkSize ); if( chunkData != NULL ) { chunksSoFar += 1; bytesSoFar += chunkSize; unsigned long numWritten = fwrite( chunkData, 1, chunkSize, outputFile ); if( numWritten == chunkSize ) { char shouldContinue = inDownloadProgressHandler( MULTISOURCE_DOWNLOAD_IN_PROGRESS, bytesSoFar, inProgressHandlerExtraArgument ); if( !shouldContinue ) { canceled = true; // call handler last time inDownloadProgressHandler( MULTISOURCE_DOWNLOAD_CANCELED, bytesSoFar, inProgressHandlerExtraArgument ); } } else { // failed to write to file, so download cannot continue inDownloadProgressHandler( MULTISOURCE_DOWNLOAD_FAILED, bytesSoFar, inProgressHandlerExtraArgument ); failed = true; } delete [] chunkData; } else { // else go on to the next host sourceIndex ++; } } // check if we got here because we ran out of hosts (another type of // failure if( !failed && !canceled && chunksSoFar < numChunks ) { inDownloadProgressHandler( MULTISOURCE_DOWNLOAD_FAILED, bytesSoFar, inProgressHandlerExtraArgument ); } fclose( outputFile ); } between-6+dfsg1.orig/minorGems/network/p2pParts/protocolUtils.cpp0000640000175000017500000000644511435543336024013 0ustar pabspabs/* * Modification History * * 2003-August-12 Jason Rohrer * Created. * * 2003-August-22 Jason Rohrer * Added function for getting a token after reading. */ #include "minorGems/network/p2pParts/protocolUtils.h" #include "minorGems/util/log/AppLog.h" #include "minorGems/util/stringUtils.h" char *readStreamUpToTag( InputStream *inInputStream, char *inTag, int inMaxCharsToRead ) { char *readCharBuffer = new char[ inMaxCharsToRead + 1 ]; int numCharsRead = 0; char tagSeen = false; char readError = false; int tagLength = strlen( inTag ); // start with empty string readCharBuffer[ numCharsRead ] = '\0'; while( numCharsRead < inMaxCharsToRead && !tagSeen && !readError ) { long numRead = inInputStream->readByte( (unsigned char *) ( &( readCharBuffer[ numCharsRead ] ) ) ); if( numRead != 1 ) { readError = true; readCharBuffer[ numCharsRead ] = '\0'; } else { numCharsRead++; // terminate and check if buffer ends with our tag readCharBuffer[ numCharsRead ] = '\0'; if( numCharsRead > tagLength ) { char *possibleBodyStart = &( readCharBuffer[ numCharsRead - tagLength ] ); if( strcmp( possibleBodyStart, inTag ) == 0 ) { tagSeen = true; } } } } if( !readError && tagSeen ) { char *returnString = stringDuplicate( readCharBuffer ); delete [] readCharBuffer; return returnString; } else { char *message = autoSprintf( "Failed to find end tag \"%s\", read %d characters:\n%s\n", inTag, numCharsRead, readCharBuffer ); AppLog::info( "readStreamUpToTag", message ); delete [] message; delete [] readCharBuffer; return NULL; } } char *readStreamUpToTagAndGetToken( InputStream *inInputStream, char *inTag, int inMaxCharsToRead, int inTokenNumber ) { // read the string char *readString = readStreamUpToTag( inInputStream, inTag, inMaxCharsToRead ); if( readString == NULL ) { return NULL; } SimpleVector *readTokens = tokenizeString( readString ); delete [] readString; // second token should be their key char *selectedToken = NULL; int numTokens = readTokens->size(); if( numTokens > inTokenNumber ) { selectedToken = stringDuplicate( *( readTokens->getElement( inTokenNumber ) ) ); } else { char *message = autoSprintf( "Looking for token %d, but only %d tokens available\n", inTokenNumber, numTokens ); AppLog::error( "readStreamUpToTagAndGetToken", message ); } for( int i=0; igetElement( i ) ); } delete readTokens; // will be NULL if not enough tokens read return selectedToken; } between-6+dfsg1.orig/minorGems/network/SocketServer.h0000640000175000017500000000347111435543335021475 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. * * 2002-March-27 Jason Rohrer * Added a timeout to accept. */ #include "minorGems/common.h" #ifndef SOCKET_SERVER_CLASS_INCLUDED #define SOCKET_SERVER_CLASS_INCLUDED #include #include "Socket.h" /** * Network socket server that listens for connections on a certain port. * * Note: Implementation for the functions defined here is provided * separately for each platform (in the mac/ linux/ and win32/ * subdirectories). * * @author Jason Rohrer */ class SocketServer { public: /** * Constructs a SocketServer and begins listening for connections. * * @param inPort the port to listen on. * @param inMaxQueuedConnections the number of connection requests * that will be queued before further requests are refused. */ SocketServer( int inPort, int inMaxQueuedConnections ); ~SocketServer(); /** * Accepts a an incoming connection on our port. * * @param inTimeoutInMilliseconds the timeout in milliseconds, * or -1 for no timeout. Defaults to -1. * @param outTimedOut pre-allocated char where timeout * flag will be returned. If non-NULL, true will * be inserted upon timeout, and false will be inserted * upon other error or no error/timeout. * Must be destroyed by caller if non-NULL. * Defaults to NULL. * * @return a socket for the accepted connection, * or NULL if a socket error/timeout occurred. */ Socket *acceptConnection( long inTimeoutInMilliseconds = -1, char *outTimedOut = NULL ); private: /** * Used by platform-specific implementations. */ void *mNativeObjectPointer; }; #endif between-6+dfsg1.orig/minorGems/network/socketTestCompile0000750000175000017500000000065711435543336022277 0ustar pabspabsg++ -g -o socketTest -I../.. socketTest.cpp linux/SocketLinux.cpp linux/SocketClientLinux.cpp linux/SocketServerLinux.cpp linux/HostAddressLinux.cpp ../system/linux/MutexLockLinux.cpp NetworkFunctionLocks.cpp g++ -g -o socketClientTest -I../.. socketClientTest.cpp linux/SocketLinux.cpp linux/SocketClientLinux.cpp linux/SocketServerLinux.cpp linux/HostAddressLinux.cpp ../system/linux/MutexLockLinux.cpp NetworkFunctionLocks.cpp between-6+dfsg1.orig/minorGems/network/linux/0000750000175000017500000000000011435543336020037 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/network/linux/gnut_net.c0000640000175000017500000002560111435543336022033 0ustar pabspabs/* Josh Pieper, (c) 2000 */ /* This file is distributed under the GPL, see file COPYING for details */ #include #include #include #ifndef WIN32 #include #include #include #include #include #include #include #include #include #endif #include #include #include #include #include #include #include #include "gnut_lib.h" #include "gnut_threads.h" #include "gnut_if.h" #include "protocol.h" uchar local_ip[4]; // uint32 net_local_ip() // // returns the local ip address // uchar *net_local_ip() { return local_ip; } int gnut_net_host() { char host[256]; struct hostent *he; int ret; g_debug(2,"entering\n"); ret=gethostname(host,sizeof(host)); if (ret<0) { perror("gnut_net_host, gethostname"); return ret; } he=gethostbyname(host); if (he==NULL) { perror("gnut_net_host, gethostbyname"); return ret; } memcpy(local_ip,he->h_addr_list[0],4); return 0; } // int net_init(char *iface) // // Does misc. net init stuff. Mostly just finds our local IP address // int net_init(char *iface) { struct sockaddr_in *sinptr=NULL; g_debug(2,"entering\n"); if (iface!=NULL) { if (inet_aton(iface,(struct in_addr *) local_ip)) { g_debug(1,"local was set by command to: %i.%i.%i.%i\n",local_ip[0],local_ip[1], local_ip[2],local_ip[3]); return 0; } } if ((sinptr = get_if_addr(iface))==NULL) { g_debug(1,"Can't get local IP address through interface, trying host name...\n"); gnut_net_host(); } else { memcpy(local_ip,&(sinptr->sin_addr),sizeof(local_ip)); } g_debug(1,"local ip is: %i.%i.%i.%i\n",local_ip[0],local_ip[1], local_ip[2],local_ip[3]); return 0; } // exactly like the real read, except that it returns -2 // if no data was read before the timeout occurred... int timed_read(int sock, char *buf, int len, int secs) { fd_set fsr; struct timeval tv; int ret; ret=fcntl(sock,F_SETFL,O_NONBLOCK); FD_ZERO(&fsr); FD_SET(sock,&fsr); tv.tv_sec=secs; tv.tv_usec=0; ret=select(sock+1,&fsr,NULL,NULL,&tv); if (ret==0) { return -2; } if (ret<0) return ret; ret=read(sock,buf,len); fcntl(sock,F_SETFL,0); return ret; } // int timed_connect(int sock, struct sockaddr *sa,int addrlen,int secs) // // just like connect except that it times out after time secs // returns -2 on timeout, otherwise same as connect // int timed_connect(int sockfd, struct sockaddr *sa, int addrlen,int secs) { int ret; fd_set fsr; struct timeval tv; int val,len; g_debug(1,"entering sock=%i secs=%i\n",sockfd,secs); ret=fcntl(sockfd,F_SETFL,O_NONBLOCK); g_debug(5,"fcntl returned %i\n",ret); if (ret<0) return ret; ret=connect(sockfd,sa,addrlen); g_debug(5,"connect returned %i\n",ret); if (ret==0) { g_debug(0,"immediate connection!\n"); // wooah! immediate connection return -2; } // if (errno != EINPROGRESS) { // perror("timed_connect, connect"); // return ret; // } FD_ZERO(&fsr); FD_SET(sockfd,&fsr); tv.tv_sec=secs; tv.tv_usec=0; ret=select(sockfd+1,NULL,&fsr,NULL,&tv); g_debug(5,"select returned %i\n",ret); if (ret==0) { // timeout g_debug(1,"timeout\n"); fcntl(sockfd,F_SETFL,0); return -2; } len=4; ret=getsockopt(sockfd,SOL_SOCKET,SO_ERROR,&val,&len); g_debug(5,"getsockopt returned %i val=%i\n",ret,val); if (ret<0) { g_debug(1,"getsockopt returned: %i\n",ret); return ret; } if (val!=0) { g_debug(3,"returning failure!\n"); return -1; } ret=fcntl(sockfd,F_SETFL,0); g_debug(1,"fcntl: %i\n",ret); g_debug(3,"returning success val=%i\n",val); return 0; } // int create_listen_socket(int * port) // // attempts to create a socket to listen on port // returns the actual port bound to in port or <0 if not // successfull // int create_listen_socket(int *port) { struct sockaddr_in sin; int sock; int ret,i; int val; g_debug(3,"entering\n"); sock=socket(AF_INET,SOCK_STREAM,6); if (sock<0) { perror("create_listen_socket, socket"); return sock; } val=1; ret=setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(val)); i=0; ret=-1; while (ret<0) { sin.sin_addr.s_addr=INADDR_ANY; sin.sin_port=htons(*port); sin.sin_family=AF_INET; ret=bind(sock,(struct sockaddr *) &sin,sizeof(struct sockaddr_in)); if (++i>50) { (*port)++; i=0; } } if (ret<0) { perror("create_listen_socket, bind"); return ret; } ret=listen(sock,5); if (ret<0) { perror("create_listen_socket, listen"); return ret; } g_debug(1,"bound to port %i\n",*port); printf("Bound to port: %i\n",*port); ret=fcntl(sock,F_SETFL,O_NONBLOCK); if (ret<0) { perror("create_listen_socket, fcntl"); return ret; } return sock; } // int read_line(int sock, char *buf, int len) // // reads a line from sock into buf, not exceeding len chars // returns 0 on EOF, -1 on error, or num of characters read // and -2 if buffer length exceeded // int read_line(int sock, char *buf, int len) { int i,ret; char c; char *ptr; ptr=buf; g_debug(3,"entering\n"); fcntl(sock,F_SETFL,0); buf[0]=0; for (i=1;i=1) perror("read_line, read"); return -1; } } buf[i]=0; g_debug(3,"returning success\n"); return i; } #ifndef PTHREADS_DRAFT4 pthread_mutex_t make_connection_mutex=PTHREAD_MUTEX_INITIALIZER; #else pthread_mutex_t make_connection_mutex; #endif struct hostent *gnut_hostent_copy(struct hostent *he) { struct hostent *n; int i,len; if (!he) return NULL; n=(struct hostent *) calloc(sizeof(struct hostent),1); memcpy(n,he,sizeof(struct hostent)); if (he->h_name) n->h_name=strdup(he->h_name); for (len=0;he->h_addr_list[len];len++); n->h_addr_list=(char **) calloc(sizeof(char *) * (len+1),1); for (i=0;ih_addr_list[i]=xmalloc(4); memcpy(n->h_addr_list[i],he->h_addr_list[i],4); } return n; } void gnut_hostent_delete(struct hostent *he) { int i,len; g_debug(1,"entering\n"); for (len=0;he->h_addr_list[len];len++); g_debug(1,"len=%i\n",len); for (i=0;ih_addr_list[i]) free(he->h_addr_list[i]); } g_debug(1,"freeing h_name\n"); if (he->h_name) free(he->h_name); g_debug(1,"freeing h_addr_list\n"); free(he->h_addr_list); g_debug(1,"freeing he\n"); free(he); g_debug(1,"returning\n"); } // int make_connection(char *host, uint port, uchar ip[4]) // // creates a socket, and attempts to make a connection to the host // named. it tries multiple resolved ip addresses if necessary, // returning the socket on success and storing the good ip number in ip // otherwise it returns <0 // // Notes: due to the fact that gethostbyname is not thread safe // we need to protect this function with a mutex // int make_connection(uchar *host, uint port, uchar ip[4]) { struct hostent *he; struct sockaddr_in sin; int i,sock=-1,ret; g_debug(1,"entering\n"); pthread_mutex_lock(&make_connection_mutex); he=gnut_hostent_copy(gethostbyname(host)); if (he==NULL) { pthread_mutex_unlock(&make_connection_mutex); return -1; } pthread_mutex_unlock(&make_connection_mutex); for (i=0,ret=-1;he->h_addr_list[i]!=NULL && ret<0;i++) { g_debug(1,"trying host %i.%i.%i.%i:%i\n", (uchar) he->h_addr_list[i][0],(uchar) he->h_addr_list[i][1], (uchar) he->h_addr_list[i][2],(uchar) he->h_addr_list[i][3],port); sock=socket(AF_INET,SOCK_STREAM,6); if (sock<0) { perror("make_connection, socket"); gnut_hostent_delete(he); return sock; } sin.sin_family=AF_INET; sin.sin_port=htons(port); memcpy(&sin.sin_addr.s_addr,he->h_addr_list[i],4); ret=timed_connect(sock,(struct sockaddr *) &sin, sizeof(struct sockaddr_in),10); g_debug(5,"timed_connect returned: %i\n",ret); if (ret<0) { g_debug(1,"host bad, closing\n"); close(sock); } else { break; } } if (ret<0 || he->h_addr_list[i]==NULL) { g_debug(1,"returning failure\n"); gnut_hostent_delete(he); return -2; } g_debug(5,"about to copy ip from slot %i\n",i); memcpy(ip,he->h_addr_list[i],4); g_debug(4,"trying to unlock mutex\n"); gnut_hostent_delete(he); g_debug(1,"returning success\n"); return sock; } // int send_packet (int sock, gnutella_packet *gpa) // // sends the packet described by gpa over socket sock // return 0 on success or <0 for error // int send_packet(int sock, gnutella_packet *gpa) { int ret; int t; g_debug(3,"entering\n"); ret=write(sock,(char *) &gpa->gh,sizeof(gnutella_hdr)); if (ret<0) { if (gnut_lib_debug>3) perror("send_packet, write header"); return ret; } memcpy(&t,gpa->gh.dlen,4); t=GUINT32_FROM_LE(t); if (t>0) { ret=write(sock,gpa->data,t); if (ret<0) { if (gnut_lib_debug>3) perror("send_packet, write data"); return ret; } } g_debug(3,"returning success\n"); return 23+t; } // int read_packet(int sock, gnutella_packet *gpa) // // reads a packet from the socket sock into the packet // structure of gpa. // returns 0 on success or <0 on error // int read_packet(int sock, gnutella_packet *gpa) { int ret; char *ptr; int left; uint dlen; int i; g_debug(3,"entering\n"); ptr=(char *) &gpa->gh; for (left=sizeof(gnutella_hdr);left>0;) { ret=timed_read(sock,ptr,left,10); g_debug(6,"timed_read returned: %i\n",ret); if (ret==-2) return 0; if (ret==0) { return -2; } else if (ret<0) { if (errno!=EINTR) { if (gnut_lib_debug>3) perror("read_packet, header"); return ret; } else ret=0; } ptr+=ret; left-=ret; } assert(left==0); memcpy(&dlen,gpa->gh.dlen,4); dlen=GUINT32_FROM_LE(dlen); while (dlen>32767 || (gpa->gh.func==129 && dlen>65536)) { // We're out of sync! I'm going to do large reads until // one returns 23, which is probably a ping packet.... g_debug(2,"out of sync! func=%i dlen=%i\n",gpa->gh.func,dlen); ptr=(char *) xmalloc(100); ret=1; i=0; while (ret>0 && ret!=23 && ret!=49) { ret=timed_read(sock,ptr,60,2); g_debug(6,"timed_read returned: %i\n",ret); if (ret==-2 || (++i>5)) { free(ptr); return 0; } } if (ret<=0) { free(ptr); return ret; } free(ptr); memcpy(&gpa->gh,ptr,23); memcpy(&dlen,gpa->gh.dlen,4); dlen=GUINT32_FROM_LE(dlen); } if (dlen>0) { gpa->data=(char *) calloc(dlen,1); ptr=gpa->data; for (left=dlen;left>0;) { ret=timed_read(sock,ptr,left,10); g_debug(6,"timed_read returned: %i\n",ret); if (ret==-2) return 0; if (ret==0) return -2; if (ret<0) { if (gnut_lib_debug>3) perror("read_packet, data"); return ret; } ptr+=ret; left-=ret; } } if (dlen>3000) g_debug(2,"OVERSIZE packet! size: %i\n",dlen); g_debug(3,"returning success\n"); return 23+dlen; } between-6+dfsg1.orig/minorGems/network/linux/socketServerTimeoutTest.compile0000750000175000017500000000016011435543336026277 0ustar pabspabsg++ -g -o socketServerTimeoutTest socketServerTimeoutTest.cpp -I../../.. SocketServerLinux.cpp SocketLinux.cpp between-6+dfsg1.orig/minorGems/network/linux/SocketClientLinux.cpp0000640000175000017500000002034211435543336024154 0ustar pabspabs/* * Modification History * * 2001-January-10 Jason Rohrer * Created. * * 2001-January-15 Jason Rohrer * Commented out a redundant print statement (it's better if these kinds * of messages are handled at a higher level). * * 2001-January-28 Jason Rohrer * Changed to comply with new initSocketFramework Socket interface. * * 2001-January-29 Jason Rohrer * Fixed an endian bug with the port number. * * 2001-November-13 Jason Rohrer * Added a missing include. * * 2001-December-12 Jason Rohrer * Changed the include order to make BSD compatible. * * 2002-August-5 Jason Rohrer * Removed use of obsolete call. * * 2002-October-13 Jason Rohrer * Added support for timeout on connect. * * 2002-October-17 Jason Rohrer * Added missing include. * Added support for BSD's version of getsockopt. * * 2002-Novenber-27 Jason Rohrer * Changed to print error number. There's a bug that needs to be fixed. * * 2002-December-2 Jason Rohrer * Fixed resource leak when connection fails. * * 2003-March-18 Jason Rohrer * Fixed a thread safety issue with gethostbyname. * * 2004-January-2 Jason Rohrer * Fixed a memory leak when host name lookup fails. * * 2004-January-4 Jason Rohrer * Added use of network function locks. * * 2006-April-25 Jason Rohrer * Added missing check for a NULL outTimedOut parameter. * * 2008-September-30 Jason Rohrer * Added support for non-blocking connect. * * 2009-April-3 Jason Rohrer * OpenBSD support. * * 2009-June-15 Jason Rohrer * Fixed bug when connect timeout not used. * * 2010-January-26 Jason Rohrer * Fixed socklen_t on later versions of MacOSX. */ #include "minorGems/network/SocketClient.h" #include "minorGems/network/NetworkFunctionLocks.h" #include "minorGems/system/MutexLock.h" #include #include #include #include #include #include #include #include #include #include #include // BSD does not define socklen_t #ifdef BSD #ifndef IPHONE #ifndef __OpenBSD__ #ifndef _SOCKLEN_T // later versions of MacOS define it and mark it typedef int socklen_t; #endif #endif #endif #endif // prototypes struct in_addr *nameToAddress( char *inAddress ); int timed_connect( int inSocketID, struct sockaddr *inSocketAddress, int inAddressLength, int inTimeoutInMilliseconds ); Socket *SocketClient::connectToServer( HostAddress *inAddress, long inTimeoutInMilliseconds, char *outTimedOut ) { if( !Socket::isFrameworkInitialized() ) { // try to init the framework int error = Socket::initSocketFramework(); if( error == -1 ) { printf( "initializing network socket framework failed\n" ); return NULL; } } int socketID = socket( AF_INET, SOCK_STREAM, 0 ); if( socketID == -1 ) { printf( "Creating socket failed, error %d.\n", errno ); return NULL; } union sock { struct sockaddr s; struct sockaddr_in i; } sock; struct in_addr *internet_address = nameToAddress( inAddress->mAddressString ); if( internet_address == NULL ) { printf( "Host name lookup failed: " ); inAddress->print(); printf( "\n" ); close( socketID ); return NULL; } sock.i.sin_family = AF_INET; sock.i.sin_port = htons( inAddress->mPort ); sock.i.sin_addr = *internet_address; int error; if( inTimeoutInMilliseconds != -1 ) { // use timeout error = timed_connect( socketID, &sock.s, sizeof( struct sockaddr ), inTimeoutInMilliseconds ); if( outTimedOut != NULL ) { if( error == -2 ) { *outTimedOut = true; if( inTimeoutInMilliseconds == 0 ) { // caller didn't want to wait at all error = 0; } else { // treat timeout as error error = -1; } } else { *outTimedOut = false; } } } else { // don't use timeout error = connect( socketID, &sock.s, sizeof( struct sockaddr ) ); } delete internet_address; if( error == -1 ) { //printf( "Connecting to host failed: " ); //inAddress->print(); //printf( "\n" ); close( socketID ); return NULL; } // package into a Socket and return it Socket *returnSocket = new Socket(); int *idSpace = new int[1]; idSpace[0] = socketID; returnSocket->mNativeObjectPointer = (void *)idSpace; if( outTimedOut != NULL && *outTimedOut ) { // not connected yet returnSocket->setConnected( false ); } return returnSocket; } /* Converts ascii text to in_addr struct. NULL is returned if the address can not be found. Result must be destroyed by caller. Adapted from the Unix Socket FAQ */ struct in_addr *nameToAddress( char *inAddress ) { struct hostent *host; static struct in_addr saddr; struct in_addr *copiedSaddr = new struct in_addr; /* First try it as aaa.bbb.ccc.ddd. */ // this is obsolete on linux // saddr.s_addr = inet_addr( inAddress ); int error = inet_aton( inAddress, &saddr ); if( error != 0 ) { // copy to avoid returning pointer to stack memcpy( copiedSaddr, &saddr, sizeof( struct in_addr ) ); return copiedSaddr; } // must keep this locked until we are done copying the in_addr out // of the returned hostent NetworkFunctionLocks::mGetHostByNameLock.lock(); char hostFound = false; host = gethostbyname( inAddress ); if( host != NULL ) { memcpy( copiedSaddr, *host->h_addr_list, sizeof( struct in_addr ) ); hostFound = true; } NetworkFunctionLocks::mGetHostByNameLock.unlock(); if( hostFound ) { return copiedSaddr; } else { delete copiedSaddr; } return NULL; } /* timed_connect adapted from gnut, by Josh Pieper */ /* Josh Pieper, (c) 2000 */ /* This file is distributed under the GPL, see file COPYING for details */ // just like connect except that it times out after time secs // returns -2 on timeout, otherwise same as connect int timed_connect( int inSocketID, struct sockaddr *inSocketAddress, int inAddressLength, int inTimeoutInMilliseconds ) { int ret; fd_set fsr; struct timeval tv; int val; socklen_t len; //g_debug(1,"entering sock=%i secs=%i\n",inSocketID,inTimeoutInSeconds); ret = fcntl( inSocketID, F_SETFL, O_NONBLOCK ); //g_debug(5,"fcntl returned %i\n",ret); if( ret < 0 ) { return ret; } ret = connect( inSocketID, inSocketAddress, inAddressLength ); //g_debug(5,"connect returned %i\n",ret); if( ret == 0 ) { //g_debug(0,"immediate connection!\n"); // wooah! immediate connection // return -2; // changed from what Josh originally returned (-2) // immediate connection *can* happen sometimes, right? // for example, when connecting to localhost... return 0; } // if (errno != EINPROGRESS) { // perror("timed_connect, connect"); // return ret; // } FD_ZERO( &fsr ); FD_SET( inSocketID, &fsr ); tv.tv_sec = inTimeoutInMilliseconds / 1000; int remainder = inTimeoutInMilliseconds % 1000; tv.tv_usec = remainder * 1000; ret = select( inSocketID+1, NULL, &fsr, NULL, &tv ); //g_debug(5,"select returned %i\n",ret); if( ret==0 ) { // timeout //g_debug(1,"timeout\n"); fcntl( inSocketID, F_SETFL, 0 ); return -2; } len = 4; ret = getsockopt( inSocketID, SOL_SOCKET, SO_ERROR, &val, &len ); //g_debug(5,"getsockopt returned %i val=%i\n",ret,val); if( ret < 0 ) { //g_debug(1,"getsockopt returned: %i\n",ret); return ret; } if (val!=0) { //g_debug(3,"returning failure!\n"); return -1; } ret = fcntl( inSocketID, F_SETFL, 0 ); //g_debug(1,"fcntl: %i\n",ret); //g_debug(3,"returning success val=%i\n",val); return 0; } between-6+dfsg1.orig/minorGems/network/linux/socketServerTimeoutTest.cpp0000640000175000017500000000226011435543336025432 0ustar pabspabs/* * Modification History * * 2002-April-12 Jason Rohrer * Created. */ #include "minorGems/network/Socket.h" #include "minorGems/network/SocketServer.h" #include void usage( char *inAppName ); int main( int inNumArgs, char **inArgs ) { if( inNumArgs != 2 ) { usage( inArgs[0] ); } int port; int numRead = sscanf( inArgs[1], "%d", &port ); if( numRead != 1 ) { usage( inArgs[0] ); } SocketServer *server = new SocketServer( port, 100 ); char timedOut; Socket *sock; printf( "waiting for connection on port %d\n", port ); sock = server->acceptConnection( 5000, &timedOut ); if( timedOut ) { printf( "timed out after 5 seconds, waiting again\n" ); sock = server->acceptConnection( 5000, &timedOut ); } if( !timedOut && sock != NULL ) { printf( "connection received\n" ); delete sock; } else { printf( "timed out again\n" ); } delete server; return 1; } void usage( char *inAppName ) { printf( "Usage:\n" ); printf( " %s port_number\n", inAppName ); exit( 1 ); } between-6+dfsg1.orig/minorGems/network/linux/gnut_lib.c0000640000175000017500000000401711435543336022011 0ustar pabspabs/* Josh Pieper, (c) 2000 */ /* This file is distributed under the GPL, see file COPYING for details */ #include #include #include #include #include #ifndef WIN32 #include #endif #ifdef MCHECK #include #endif #include "gnut_lib.h" #include "gnut_threads.h" int gnut_mprobe(void *d) { #ifdef MCHECK return mprobe(d); #else return 0; #endif } #ifndef HAVE_XMALLOC #ifndef xmalloc char *xmalloc(int size) { char *ptr; ptr=malloc(size); if (!ptr) { g_debug(0,"malloc(%d) failed!\n", size); exit(1); } return ptr; } #endif #endif char *expand_path(char *a) { char *b; if (strncmp(a,"~/", 2)==0) { #ifndef WIN32 char *c; c=getenv("HOME"); #else char c[MAX_PATH]; GetWindowsDirectory(c, MAX_PATH); #endif b=(char *)xmalloc(strlen(a)+strlen(c)+1); strcpy(b, c); strcat(b, &a[1]); return b; } b=(char *) xmalloc(strlen(a)+1); strcpy(b,a); return b; } int gnut_lib_debug=0; #ifndef PTHREADS_DRAFT4 pthread_mutex_t _g_debug_mutex=PTHREAD_MUTEX_INITIALIZER; #else pthread_mutex_t _g_debug_mutex; #endif #ifndef WIN32 void _g_debug(char *file, int line, int num, char *format, ...) { va_list argp; if (gnut_lib_debug>=num) { pthread_mutex_lock(&_g_debug_mutex); fprintf(stderr,"%i %s:%i > ", getpid(),file,line); fflush(stdout); va_start(argp,format); vfprintf(stderr,format,argp); va_end(argp); pthread_mutex_unlock(&_g_debug_mutex); } } #else void g_debug(int a, char *format, ...) { va_list argp; if (gnut_lib_debug>=a) { pthread_mutex_lock(&_g_debug_mutex); fprintf(stderr,"%li > ", (long) pthread_self()); va_start(argp,format); vfprintf(stderr,format,argp); va_end(argp); pthread_mutex_unlock(&_g_debug_mutex); } } #endif char *gnut_strdelimit(char *string, char *delim, char new_delim) { char *c; for (c=string;*c;c++) { if (strchr(delim,*c)) *c=new_delim; } return string; } between-6+dfsg1.orig/minorGems/network/linux/SocketServerLinux.cpp0000640000175000017500000001356311435543336024213 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. * * 2001-January-15 Jason Rohrer * Commented out redundant status messages that should be handled at a * higher level. * * 2001-January-28 Jason Rohrer * Changed to comply with new initSocketFramework Socket interface. * * 2001-January-29 Jason Rohrer * Fixed an endian bug with the port number. * * 2001-May-12 Jason Rohrer * Added a port number to the "bad socket bind" error message. * * 2001-November-13 Jason Rohrer * Added a missing include. * * 2001-December-12 Jason Rohrer * Changed some type usage and the include order to make BSD compatible. * Added a BSD definition test to make socklen_t type compatible * on both BSD and Linux. * * 2002-March-27 Jason Rohrer * Added a timeout to accept. * * 2002-March-29 Jason Rohrer * Fixed a bug in return value when accept fails. * * 2002-April-11 Jason Rohrer * Changed to use select instead of poll to make it more portable. * Fixed a bug in the timeout implementation. * * 2002-April-12 Jason Rohrer * Changed to use poll on Linux and select on BSD, * since select does not seem to work on LinuxX86. * Fixed X86 accept/select bug by getting rid of union * and some unused parameters (it seems that stack space was a problem). * * 2004-February-23 Jason Rohrer * Added socket option to clear up lingering bound ports after shutdown. * Changed to close server socket instead of using shutdown. * * 2010-January-26 Jason Rohrer * Fixed socklen_t on later versions of MacOSX. */ #include "minorGems/network/SocketServer.h" #include #include #include #include #include #include #include // BSD does not define socklen_t #ifdef BSD #ifndef IPHONE #ifndef __OpenBSD__ #ifndef _SOCKLEN_T // later versions of MacOS define it and mark it typedef int socklen_t; #endif #endif #endif #endif #ifndef BSD // poll not available on BSD #include #endif /** * BSD Compilation note: * * Use g++ option -DBSD to define the BSD preprocessor variable. */ SocketServer::SocketServer( int inPort, int inMaxQueuedConnections ) { int error = 0; if( !Socket::isFrameworkInitialized() ) { // try to init the framework int error = Socket::initSocketFramework(); if( error == -1 ) { printf( "initializing network socket framework failed\n" ); exit( 1 ); } } // create the socket int sockID = socket( AF_INET, SOCK_STREAM, 0 ); if( sockID == -1 ) { printf( "Failed to construct a socket\n" ); exit( 1 ); } // store socket id in native object pointer int *idStorage = new int[1]; idStorage[0] = sockID; mNativeObjectPointer = (void *)idStorage; // this setsockopt code partially copied from gnut // set socket option to enable reusing addresses so that the socket is // unbound immediately when the server is shut down // (otherwise, rebinding to the same port will fail for a while // after the server is shut down) int reuseAddressValue = 1; error = setsockopt( sockID, SOL_SOCKET, // socket-level option SO_REUSEADDR, // reuse address option &reuseAddressValue, // value to set for this option sizeof( reuseAddressValue) ); // size of the value if( error == -1 ) { printf( "Failed to set socket options\n" ); exit( 1 ); } // bind socket to the port struct sockaddr_in address; address.sin_family = AF_INET; address.sin_port = htons( inPort ); address.sin_addr.s_addr = INADDR_ANY; error = bind( sockID, (struct sockaddr *) &address, sizeof( address ) ); if( error == -1 ) { printf( "Bad socket bind, port %d\n", inPort ); exit( 1 ); } // start listening for connections error = listen( sockID, inMaxQueuedConnections ); if( error == -1 ) { printf( "Bad socket listen\n" ); exit(1); } } SocketServer::~SocketServer() { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; close( socketID ); delete [] socketIDptr; } Socket *SocketServer::acceptConnection( long inTimeoutInMilliseconds, char *outTimedOut ) { // printf( "Waiting for a connection.\n" ); // extract socket id from native object pointer int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; if( outTimedOut != NULL ) { *outTimedOut = false; } if( inTimeoutInMilliseconds != -1 ) { // if we have a timeout specified, select before accepting // this found in the Linux man page for select, // but idea (which originally used poll) was found // in the Unix Socket FAQ fd_set rfds; struct timeval tv; int retval; // insert our socket descriptor into this set FD_ZERO( &rfds ); FD_SET( socketID, &rfds ); // convert our timeout into the structure's format tv.tv_sec = inTimeoutInMilliseconds / 1000; tv.tv_usec = ( inTimeoutInMilliseconds % 1000 ) * 1000 ; retval = select( socketID + 1, &rfds, NULL, NULL, &tv ); if( retval == 0 ) { // timeout if( outTimedOut != NULL ) { *outTimedOut = true; } return NULL; } } int acceptedID = accept( socketID, NULL, NULL ); if( acceptedID == -1 ) { printf( "Failed to accept a network connection.\n" ); return NULL; } else { Socket *acceptedSocket = new Socket(); int *idStorage = new int[1]; idStorage[0] = acceptedID; acceptedSocket->mNativeObjectPointer = (void *)idStorage; //printf( "Connection received.\n" ); return acceptedSocket; } } between-6+dfsg1.orig/minorGems/network/linux/HostAddressLinux.cpp0000640000175000017500000001115011435543336024005 0ustar pabspabs/* * Modification History * * 2001-December-14 Jason Rohrer * Created. * Fixed a typo. * Added a missing include. * * 2002-March-25 Jason Rohrer * Added function for conversion to numerical addresses. * * 2002-March-26 Jason Rohrer * Changed to use strdup. * Fixed problem on some platforms where local address does * not include domain name. * Fixed so that numerical address is actually retrieved by * getNumericalAddress(). * * 2002-April-6 Jason Rohrer * Replaced use of strdup. * * 2002-April-8 Jason Rohrer * Changed to return numerical address from getLocalAddress, * since it is simpler, and we probably want the numerical * address anyway. * This new implementation also fixes a BSD domain-name lookup bug. * Changed to check if address is numerical before * performing a lookup on it. * * 2002-July-10 Jason Rohrer * Fixed a bug that occurs when fetching numerical address fails. * * 2004-January-4 Jason Rohrer * Added use of network function locks. * * 2009-December-22 Jason Rohrer * New method of getting local address. * * 2010-April-23 Jason Rohrer * ifa->if_addr can be NULL. */ #include "minorGems/network/HostAddress.h" #include "minorGems/network/NetworkFunctionLocks.h" #include "minorGems/util/stringUtils.h" #include #include #include #include #include #include #include HostAddress *HostAddress::getLocalAddress() { int bufferLength = 200; char *buffer = new char[ bufferLength ]; // old method, tended to return a 127.0.0.1 address //gethostname( buffer, bufferLength ); // new method, iterate through interfaces struct ifaddrs *ifaddr, *ifa; if( getifaddrs( &ifaddr ) == -1 ) { delete [] buffer; return NULL; } // Walk through linked list, maintaining head pointer so we // can free list later // stop when we find an addr other than 127.0.0.1 char found = false; for( ifa = ifaddr; ifa != NULL && !found; ifa = ifa->ifa_next) { // only consider IPv4 // NULL check, too, because on at least one VPN, NULL // addresses are present in list? if( ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_INET ) { int s = getnameinfo( ifa->ifa_addr, sizeof( struct sockaddr_in ), buffer, bufferLength, NULL, 0, NI_NUMERICHOST ); if( s != 0 ) { printf("getnameinfo() failed: %s\n", gai_strerror( s ) ); delete [] buffer; return NULL; } if( strcmp( buffer, "127.0.0.1" ) != 0 ) { found = true; } } } freeifaddrs(ifaddr); if( found ) { char *numerical = stringDuplicate( buffer ); delete [] buffer; // this class will destroy name for us HostAddress *numericalAddress = new HostAddress( numerical, 0 ); return numericalAddress; } else { delete [] buffer; return NULL; } } HostAddress *HostAddress::getNumericalAddress() { // make sure we're not already numerical if( this->isNumerical() ) { return this->copy(); } // need to use two function locks here // first, lock for gethostbyname NetworkFunctionLocks::mGetHostByNameLock.lock(); struct hostent *host = gethostbyname( mAddressString ); if (host != NULL) { // this line adapted from the // Unix Socket FAQ struct in_addr *inetAddress = (struct in_addr *) *host->h_addr_list; // now lock for inet_ntoa NetworkFunctionLocks::mInet_ntoaLock.lock(); // the returned string is statically allocated, so copy it char *inetAddressString = stringDuplicate( inet_ntoa( *inetAddress ) ); NetworkFunctionLocks::mInet_ntoaLock.unlock(); // done with returned hostent now, so unlock first lock NetworkFunctionLocks::mGetHostByNameLock.unlock(); return new HostAddress( inetAddressString, mPort ); } else { // unlock first lock before returning NetworkFunctionLocks::mGetHostByNameLock.unlock(); return NULL; } } char HostAddress::isNumerical() { struct in_addr addressStruct; int isValid = inet_aton( mAddressString, &addressStruct ); if( isValid == 0 ) { return false; } else { return true; } } between-6+dfsg1.orig/minorGems/network/linux/socketSelectAcceptBug.cpp0000640000175000017500000000600711435543336024755 0ustar pabspabs/* * Demonstration of "accept after select" socket bug. * * This program works fine on: * LinuxPPC, FreeBSD, and MacOSX * * This program does not work on: * LinuxX86 Kernel 2.4 * (accept fails after select returns) * * This bug has something to do with the size of the * variables on the stack... * Getting rid of the union (which is unnecessary) seems * to fix the problem. * * * Jason Rohrer * 2002-April-12 * rohrer@cse.ucsc.edu */ #include #include #include #include #include #include #include #include union sock { struct sockaddr s; struct sockaddr_in i; } sock; void usage( char *inAppName ); int acceptConnection( int inSocketID, long inTimeoutMS ); int port; int main( int inNumArgs, char **inArgs ) { if( inNumArgs != 2 ) { usage( inArgs[0] ); } int numRead = sscanf( inArgs[1], "%d", &port ); // create a socket and start listening for connections printf( "Creating socket\n" ); int socketID = socket( AF_INET, SOCK_STREAM, 0 ); if( socketID == -1 ) { printf( "Socket creation failed\n" ); exit( 1 ); } // bind socket to the port union sock sockAddress; sockAddress.i.sin_family = AF_INET; sockAddress.i.sin_port = htons( port ); sockAddress.i.sin_addr.s_addr = INADDR_ANY; printf( "Binding to socket at port %d\n", port ); int error = bind( socketID, &(sockAddress.s), sizeof( struct sockaddr ) ); if( error == -1 ) { printf( "Bad socket bind, port %d\n", port ); exit( 1 ); } // start listening for connections, max queued = 100 connections printf( "Starting to listen to socket\n" ); error = listen( socketID, 100 ); if( error == -1 ) { printf( "Bad socket listen\n" ); exit(1); } // no we're listening to this socket int acceptedID = acceptConnection( socketID, 50000 ); if( acceptedID != -1 ) { // close the connection shutdown( acceptedID, SHUT_RDWR ); close( acceptedID ); } shutdown( socketID, SHUT_RD ); return 1; } int acceptConnection( int inSocketID, long inTimeoutMS ) { // use select to timeout if no connection received in 10 seconds struct timeval tv; socklen_t addressLength; union sock acceptedAddress; int acceptedID = accept( inSocketID, &( acceptedAddress.s ), &addressLength ); if( acceptedID == -1 ) { printf( "Failed to accept the connection\n" ); printf( "Error = %d\n", errno ); return -1; } else { printf( "Successfully accepted the connection\n" ); return acceptedID; } } void usage( char *inAppName ) { printf( "Usage:\n" ); printf( " %s port_number\n", inAppName ); exit( 1 ); } between-6+dfsg1.orig/minorGems/network/linux/socketSelectAcceptBug.compile0000750000175000017500000000007111435543336025620 0ustar pabspabsg++ -g -o socketSelectAcceptBug socketSelectAcceptBug.cppbetween-6+dfsg1.orig/minorGems/network/linux/SocketLinux.cpp0000640000175000017500000002312311435543336023015 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. * * 2001-January-10 Jason Rohrer * Fixed a bug in the receive code (in use of timed_read). * * 2001-January-15 Jason Rohrer * Added a safeguard against receives that exceed the * network buffer size. * * 2001-January-28 Jason Rohrer * Changed to comply with new initSocketFramework Socket interface. * Added a close() call to the destructor. * * 2001-January-29 Jason Rohrer * Fixed compile bug by including unistd.h for close call. * * 2001-November-13 Jason Rohrer * Changed to use ::send function instead of __send function. * Changed timeout parameter to signed, since -1 is a possible argument. * * 2001-December-12 Jason Rohrer * Changed the include order to make BSD compatible. * * 2002-August-2 Jason Rohrer * Changed to ignore SIGPIPE. * Added functon for getting remote host address. * Added fix for linux-BSD differences. * * 2002-November-15 Jason Rohrer * Fixed a security hole when getting the remote host address. * * 2003-February-3 Jason Rohrer * Added a function for getting the local host address from a socket. * * 2003-February-21 Jason Rohrer * Fixed a BSD compatibility bug. * * 2004-January-4 Jason Rohrer * Added use of network function locks. * * 2004-March-23 Jason Rohrer * Removed timeout error message. * * 2004-December13 Jason Rohrer * Added a breakConnection function. * * 2005-July-5 Jason Rohrer * Added port number when getting address of remote host. * * 2006-May-28 Jason Rohrer * Changed timeout behavior slightly to support emulation of non-blocking mode. * Added support for non-blocking sends. * * 2006-June-5 Jason Rohrer * Fixed error checking for non-blocking sends. * * 2006-June-23 Jason Rohrer * Changed implementation of non-blocking sends to work on Mac. * * 2008-September-30 Jason Rohrer * Added support for non-blocking connect. * Fixed close-detection in non-blocking read. * * 2009-April-3 Jason Rohrer * OpenBSD support. * * 2010-January-26 Jason Rohrer * Fixed socklen_t on later versions of MacOSX. * * 2010-January-26 Jason Rohrer * Added support for disabling Nagle algorithm. */ #include "minorGems/network/Socket.h" #include "minorGems/network/NetworkFunctionLocks.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // BSD does not define socklen_t #ifdef BSD #ifndef IPHONE #ifndef __OpenBSD__ #ifndef _SOCKLEN_T // later versions of MacOS define it and mark it typedef int socklen_t; #endif #endif #endif #endif // prototypes int timed_read( int inSock, unsigned char *inBuf, int inLen, long inMilliseconds ); /** * Linux-specific implementation of the Socket class member functions. * * May also be compatible with other POSIX-like systems. * * To compile: * no special options needed */ char Socket::sInitialized = false; int Socket::initSocketFramework() { // ignore SIGPIPE, which occurs on send whenever the receiver // has closed the socket signal(SIGPIPE, SIG_IGN); sInitialized = true; return 0; } Socket::~Socket() { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; if( !mIsConnectionBroken ) { shutdown( socketID, SHUT_RDWR ); mIsConnectionBroken = true; } close( socketID ); delete [] socketIDptr; } int Socket::isConnected() { if( mConnected ) { return 1; } int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; int ret; fd_set fsr; struct timeval tv; int val; socklen_t len; FD_ZERO( &fsr ); FD_SET( socketID, &fsr ); // check if connection event waiting right now // timeout of 0 tv.tv_sec = 0; tv.tv_usec = 0; ret = select( socketID + 1, NULL, &fsr, NULL, &tv ); if( ret==0 ) { // timeout return 0; } // no timeout // error? len = 4; ret = getsockopt( socketID, SOL_SOCKET, SO_ERROR, &val, &len ); if( ret < 0 ) { // error return -1; } if( val != 0 ) { // error return -1; } // success mConnected = true; return 1; } void Socket::setNoDelay( int inValue ) { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; int flag = inValue; setsockopt( socketID, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int) ); } int Socket::send( unsigned char *inBuffer, int inNumBytes, char inAllowedToBlock, char inAllowDelay ) { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; if( inAllowedToBlock ) { if( ! inAllowDelay ) { // turn nodelay on setNoDelay( 1 ); } int returnVal = ::send( socketID, inBuffer, inNumBytes, 0 ); if( ! inAllowDelay ) { // turn nodelay back off setNoDelay( 0 ); } return returnVal; } else { // set to non-blocking mode int result = fcntl( socketID, F_SETFL, O_NONBLOCK ); if( result < 0 ) { return result; } if( ! inAllowDelay ) { // turn nodelay on setNoDelay( 1 ); } int returnValue = ::send( socketID, inBuffer, inNumBytes, // no flags 0 ); if( ! inAllowDelay ) { // turn nodelay back off setNoDelay( 0 ); } // back into blocking mode result = fcntl( socketID, F_SETFL, 0 ); if( result < 0 ) { return result; } if( returnValue == -1 && errno == EAGAIN ) { return -2; } else { return returnValue; } } } int Socket::receive( unsigned char *inBuffer, int inNumBytes, long inTimeout ) { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; if( inTimeout == -1 ) { // use MSG_WAITALL flag here to block until inNumBytes has arrived return recv( socketID, inBuffer, inNumBytes, MSG_WAITALL ); } else { return timed_read( socketID, inBuffer, inNumBytes, inTimeout ); } } void Socket::breakConnection() { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; if( !mIsConnectionBroken ) { shutdown( socketID, SHUT_RDWR ); mIsConnectionBroken = true; } close( socketID ); } HostAddress *Socket::getRemoteHostAddress() { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; // adapted from Unix Socket FAQ socklen_t len; struct sockaddr_in sin; len = sizeof sin; int error = getpeername( socketID, (struct sockaddr *) &sin, &len ); if( error ) { return NULL; } // this is potentially insecure, since a fake DNS name might be returned // we should use the IP address only // // struct hostent *host = gethostbyaddr( (char *) &sin.sin_addr, // sizeof sin.sin_addr, // AF_INET ); NetworkFunctionLocks::mInet_ntoaLock.lock(); // returned string is statically allocated, copy it char *ipAddress = stringDuplicate( inet_ntoa( sin.sin_addr ) ); NetworkFunctionLocks::mInet_ntoaLock.unlock(); int port = ntohs( sin.sin_port ); return new HostAddress( ipAddress, port ); } HostAddress *Socket::getLocalHostAddress() { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; // adapted from GTK-gnutalla code, and elsewhere struct sockaddr_in addr; socklen_t len = sizeof( struct sockaddr_in ); int result = getsockname( socketID, (struct sockaddr*)( &addr ), &len ); if( result == -1 ) { return NULL; } else { char *stringAddress = inet_ntoa( addr.sin_addr ); return new HostAddress( stringDuplicate( stringAddress ), 0 ); } } /* timed_read adapted from gnut, by Josh Pieper */ /* Josh Pieper, (c) 2000 */ /* This file is distributed under the GPL, see file COPYING for details */ // exactly like the real read, except that it returns -2 // if no data was read before the timeout occurred... int timed_read( int inSock, unsigned char *inBuf, int inLen, long inMilliseconds ) { fd_set fsr; struct timeval tv; int ret; //ret = fcntl( inSock, F_SETFL, O_NONBLOCK ); FD_ZERO( &fsr ); FD_SET( inSock, &fsr ); tv.tv_sec = inMilliseconds / 1000; int remainder = inMilliseconds % 1000; tv.tv_usec = remainder * 1000; ret = select( inSock + 1, &fsr, NULL, NULL, &tv ); if( ret==0 ) { // printf( "Timed out waiting for data on socket receive.\n" ); return -2; } if( ret<0 ) { printf( "Selecting socket during receive failed.\n" ); return ret; } // do not use MSG_WAITALL flag here, since we just want to return // data that is available ret = recv( inSock, inBuf, inLen, 0 ); if( ret == 0 ) { // select came back as 1, but no data there // connection closed on remote end return -1; } //fcntl( inSock, F_SETFL, 0 ); return ret; } between-6+dfsg1.orig/minorGems/network/linux/gnut_lib.h0000640000175000017500000000435211435543336022020 0ustar pabspabs/* Josh Pieper, (c) 2000 */ /* This file is distributed under the GPL, see file COPYING for details */ #ifndef GNUT_LIB_H #define GNUT_LIB_H 0 #include #ifndef WIN32 #include #include #endif #ifdef DMALLOC #include #endif #ifndef MIN #define MIN(a,b) (((a < b)) ? (a) : (b)) #define MAX(a,b) (((a > b)) ? (a) : (b)) #endif #ifndef __bswap_16 #define __bswap_16(x) \ ((((x) >> 8) & 0xff) | (((x) &0xff) <<8)) #endif #ifndef __bswap_32 #define __bswap_32(x) \ ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) #endif #ifndef GUINT16_TO_LE #ifdef WORDS_BIGENDIAN #define GUINT16_TO_LE(x) __bswap_16(x) #define GUINT32_TO_LE(x) __bswap_32(x) #define GUINT16_FROM_LE(x) __bswap_16(x) #define GUINT32_FROM_LE(x) __bswap_32(x) #else #define GUINT16_TO_LE(x) (x) #define GUINT32_TO_LE(x) (x) #define GUINT16_FROM_LE(x) (x) #define GUINT32_FROM_LE(x) (x) #endif #endif typedef unsigned int uint32; typedef unsigned short uint16; typedef unsigned char uchar; #ifndef WIN32 typedef unsigned long long uint64; //#define g_debug(num, format, args... ) #define g_debug(num, format, args... ) _g_debug(__FUNCTION__,__LINE__, num, format, ##args) void _g_debug(char *,int,int num, char *,...); #endif extern int gnut_lib_debug; int gnut_mprobe(void *); char *gnut_strdelimit(char *string, char *delimeters, char new_delim); char *expand_path(char *); #ifndef xmalloc char *xmalloc(int size); #endif #ifdef WIN32 #include #define VERSION "0.3.22/win32" void g_debug(int, char *, ...); typedef unsigned __int64 uint64; typedef unsigned int uint; #define sleep Sleep char *strtok_r(char *, const char *, char **); int getopt(int argc, char *argv[], char *); extern char *optarg; extern int optind; #define strncasecmp strnicmp #define inet_aton(string, ip) (ip)->s_addr = inet_addr(string) #define write(sock, buf, len) send(sock, buf, len, 0) #define read(sock, buf, len) recv(sock, buf, len, 0) #define close(sock) closesocket(sock) #define F_SETFL 1 #define O_NONBLOCK 1 int fcntl(int sock, int, uint); #define flock(a,b) 0 #endif #endif between-6+dfsg1.orig/minorGems/network/Socket.h0000640000175000017500000002304511435543335020305 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. * * 2001-January-28 Jason Rohrer * Added a static framework init function. * * 2001-November-13 Jason Rohrer * Changed timeout parameter to signed, since -1 is a possible argument. * * 2002-March-29 Jason Rohrer * Added Fortify inclusion. * * 2002-August-2 Jason Rohrer * Added functon for getting remote host address. * * 2003-February-3 Jason Rohrer * Added a function for getting the local host address from a socket. * * 2003-August-12 Jason Rohrer * Added more verbose comment about receive timeout parameter. * Added a function for flushing socket sends. * * 2003-November-20 Jason Rohrer * Made flush function robust against bogus receive return values. * * 2004-December13 Jason Rohrer * Added a breakConnection function. * * 2005-July-5 Jason Rohrer * Added port number when getting address of remote host. * * 2006-May-28 Jason Rohrer * Changed timeout behavior slightly to support emulation of non-blocking mode. * Added support for non-blocking sends. * * 2008-September-30 Jason Rohrer * Added support for non-blocking connect. * * 2010-January-26 Jason Rohrer * Added support for disabling Nagle algorithm. */ #include "minorGems/common.h" #ifndef SOCKET_CLASS_INCLUDED #define SOCKET_CLASS_INCLUDED #include "minorGems/network/HostAddress.h" #include "minorGems/system/Time.h" #ifdef FORTIFY #include "minorGems/util/development/fortify/fortify.h" #endif /** * Network socket. Does not contain an interface for listening to connections * (see SocketServer for these interfaces) or for establishing connections * (see SocketClient for these interfaces). * * Note: Implementation for the functions defined here is provided * separately for each platform (in the mac/ linux/ and win32/ * subdirectories). * * @author Jason Rohrer */ class Socket { public: /** * Constructor for a socket. * * Should not be called directly. Use SocketClient or SocketServer * to obtain an outbound or inbound socket connection. */ Socket(); // destroying a Socket closes the connection ~Socket(); /** * Initializes the socket framework. Must be called * once by program before sockets are used. Note * that SocketClient and SocketServer both should call * init automatically when they are first used. * * @return 0 on success, or -1 on failure. */ static int initSocketFramework(); /** * Gets whether the socket framework has been initialized. * * @return true if the framework has been initialized. */ static char isFrameworkInitialized(); /** * For outbound sockets that were opened in non-blocking mode: * * Get whether socket is connected yet. * * @return 1 on success, 0 on still waiting, -1 on error. */ int isConnected(); /** * Sends bytes through this socket. * * @param inBuffer the buffer of bytes to send. * @param inNumBytes the number of bytes to send. * @param inAllowedToBlock set to false to prevent blocking. * Defaults to true. * @param inAllowDelay set to false to disable Nagle algorithm, * where a buffer should be sent NOW without waiting for * more data accumulation. * Defaults to true. * * @return the number of bytes sent successfully, * or -1 for a socket error. * Returns -2 if not allowed to block and the operation * would block. */ int send( unsigned char *inBuffer, int inNumBytes, char inAllowedToBlock = true, char inAllowDelay = true ); /** * Receives bytes from this socket. * * @param inBuffer the buffer where received bytes will be put. * Must be pre-allocated memory space. * @param inNumBytes the number of bytes to read from the socket. * @param inTimeout the timeout for this receive operation in * milliseconds. Set to -1 for an infinite timeout. * -2 is returned from this call in the event of a timeout. * If timeout is set, only available data is returned (up * to, but not more than inNumBytes). The socket does not * wait for all inNumBytes to become available before returning. * Thus, a timeout return value (-2) means no data was available * before the timeout. If some data is available, we never * time out. If no timeout is set (-1 for infinite), the socket * waits for all inNumBytes to arrive before returning. * Thus, setting a timeout of 0 effectively puts the socket * into non-blocking mode. * * @return the number of bytes read successfully, * or -1, -2 for a socket error or timeout, respectively. */ int receive( unsigned char *inBuffer, int inNumBytes, long inTimeout ); /** * Flushes sent data through the socket. * * Intended to be called before deleting the socket to ensure * that data goes through. The mechanism used by this function * does not guarantee that data goes through, but it works * better than simply closing the socket on many platforms. * * The method used by this call works best if the remote * host closes the connection. For example, if we send the * remote host a "connection closing" indicator, then * call writeFlushBeforeClose, and the remote host closes * the connection upon receiving the indicator, all of our * sent data will be received by the remote host after * writeFlushBeforeClose returns (assuming that the maximum * time is long enough for the remote host to actually close * the connection). * * Good maximum times should be in the several-second range, * though the Apache system uses 30 seconds. For slow connections, * this might be necessary. * * This call will cause any received data to be discarded. * * This call DOES NOT close the socket. The socket must be deleted * as usual after this call returns. * * @param inMaxTimeInMilliseconds the maximum time to wait * in milliseconds. This call may block slightly longer than * this if the remote host is still sending data. */ void sendFlushBeforeClose( int inMaxTimeInMilliseconds ); /** * Forces this socket's connection to break, causing any blocked * send or receive operations to fail. * * Note that this operation is inherently not thread-safe, so * some external mechanism must be used to ensure that the socket * is not destroyed by another thread before breakConnection is called. * The SocketManager class is one such external mechanism. */ void breakConnection(); /** * Gets the host connected to the other end of this socket. * * @return the address of the remote host, or NULL if obtaining * the address fails. The port of the returned address * will always be set to the port that the host is connecting from. * Must be destroyed by caller if non-NULL. */ HostAddress *getRemoteHostAddress(); /** * Gets the local address attached to this socket. * * Getting the local address from a socket is more * accurate than non-connected methods (for example, the methods * used in HostAddress.h implementations. * * @return the address of the local host, or NULL if obtaining * the address fails. The port of the returned address * will always be set to 0. * Must be destroyed by caller if non-NULL. */ HostAddress *getLocalHostAddress(); /** * Used by platform-specific implementations. */ void *mNativeObjectPointer; // called by socket client to set connected status void setConnected( char inConnected ) { mConnected = inConnected; } private: static char sInitialized; char mConnected; char mIsConnectionBroken; // toggle Nagle algorithm (inValue=1 turns it off) void setNoDelay( int inValue ); }; inline Socket::Socket() : mConnected( true ), mIsConnectionBroken( false ) { } inline char Socket::isFrameworkInitialized() { return sInitialized; } inline void Socket::sendFlushBeforeClose( int inMaxTimeInMilliseconds ) { unsigned char *tempBuffer = new unsigned char[1]; int numRead = -2; int timeout = 1000; if( timeout > inMaxTimeInMilliseconds ) { timeout = inMaxTimeInMilliseconds; } long totalTimeout = 0; unsigned long startSec; unsigned long startMsec; Time::getCurrentTime( &startSec, &startMsec ); // keep reading data from socket until we get an error // or wait too long (pass our max timeout) while( numRead != -1 && totalTimeout < inMaxTimeInMilliseconds ) { numRead = this->receive( tempBuffer, 1, timeout ); // track total time whether the receive timed out or not totalTimeout = (long)( Time::getMillisecondsSince( startSec, startMsec ) ); } delete [] tempBuffer; } #endif between-6+dfsg1.orig/minorGems/network/socketClientTest.cpp0000640000175000017500000000560311435543336022700 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. * * 2001-January-28 Jason Rohrer * Added more output. * Changed so that it doesn't sleep in the middle of a block * since the requirements of the socket interface have changed * and implementations no longer have to support this behavior. * * 2001-December-12 Jason Rohrer * Changed to use new HostAddress constructor. * * 2002-July-30 Jason Rohrer * Fixed a bug in localhost address. Added a test of streams. * * 2002-July-31 Jason Rohrer * Changed to test multiple blocks. * * 2002-December-2 Jason Rohrer * Changed to test socket creation failure. * Added counter to output. * * 2002-February-4 Jason Rohrer * Added test of getting local address from socket. */ #include "Socket.h" #include "SocketStream.h" #include "SocketServer.h" #include "SocketClient.h" #include "HostAddress.h" #include int main() { char *name = new char[99]; sprintf( name, "63.249.65.249" ); //char *name = new char[99]; //sprintf( name, "192.168.1.2" ); //char *name = "192.168.1.1"; //int addressLength = 11; //char *name = "monolith.2y.net"; //int addressLength = 15; int port = 5158; HostAddress *address = new HostAddress( name, port ); printf( "Trying to connect to server: " ); address->print(); printf( "\n" ); Socket *sock; int numConnections = 0; while( true ) { sock = SocketClient::connectToServer( address ); if( sock == NULL ) { printf( "%d Connecting to server failed\n", numConnections ); //return 1; } else { printf( "%d Connection established\n", numConnections ); HostAddress *localAddress = sock->getLocalHostAddress(); if( localAddress != NULL ) { printf( "Our local address (fetched from socket) is " ); localAddress->print(); printf( "\n" ); delete localAddress; } delete sock; } //usleep( 1000 ); numConnections++; } int numBytes = 4000; unsigned char *buffer = new unsigned char[numBytes]; for( int i=0; iwrite( buffer, numBytes ); printf( "Sent %d successfully,\tcount = %d\n", numSent, count ); count++; } int checksum = 0; for( int i=0; i /** * A SocketStream that logs inbound and outbound data. * * @author Jason Rohrer */ class LoggingSocketStream : public SocketStream { public: /** * Constructs a SocketStream. * * @param inSocket the newtork socket wrapped by this stream. * inSocket is NOT destroyed when the stream is destroyed. * @param inEnableInboundLog set to true to enable inbound logging. * @param inEnableOutboundLog set to true to enable outbound logging. * @param inLogSizeLimit the size limit of each log (both inbound * and outbound), in bytes. * Logging will stop after inLogSizeLimit bytes have been * written to each log. * @param inLogNamePrefix a string that will be used to name * the log files (appending .in and .out for the two logs). * Should be unique. * Must be destroyed by caller. */ LoggingSocketStream( Socket *inSocket, char inEnableInboundLog, char inEnableOutboundLog, unsigned long inLogSizeLimit, char *inLogNamePrefix ); virtual ~LoggingSocketStream(); // overrides the SocketStream implementations long read( unsigned char *inBuffer, long inNumBytes ); long write( unsigned char *inBuffer, long inNumBytes ); protected: char mEnableInboundLog; char mEnableOutboundLog; unsigned long mLogSizeLimit; FILE *mInboundLogFile; FILE *mOutboundLogFile; unsigned long mInboundSizeSoFar; unsigned long mOutboundSizeSoFar; }; inline LoggingSocketStream::LoggingSocketStream( Socket *inSocket, char inEnableInboundLog, char inEnableOutboundLog, unsigned long inLogSizeLimit, char *inLogNamePrefix ) : SocketStream( inSocket ), mEnableInboundLog( inEnableInboundLog ), mEnableOutboundLog( inEnableOutboundLog ), mLogSizeLimit( inLogSizeLimit ), mInboundLogFile( NULL ), mOutboundLogFile( NULL ), mInboundSizeSoFar( 0 ), mOutboundSizeSoFar( 0 ) { if( mEnableInboundLog ) { char *inboundFileName = autoSprintf( "%s.in", inLogNamePrefix ); mInboundLogFile = fopen( inboundFileName, "wb" ); delete [] inboundFileName; } if( mEnableOutboundLog ) { char *outboundFileName = autoSprintf( "%s.out", inLogNamePrefix ); mOutboundLogFile = fopen( outboundFileName, "wb" ); delete [] outboundFileName; } } inline LoggingSocketStream::~LoggingSocketStream() { if( mInboundLogFile != NULL ) { fclose( mInboundLogFile ); mInboundLogFile = NULL; } if( mOutboundLogFile != NULL ) { fclose( mOutboundLogFile ); mOutboundLogFile = NULL; } } inline long LoggingSocketStream::read( unsigned char *inBuffer, long inNumBytes ) { long returnVal = SocketStream::read( inBuffer, inNumBytes ); if( mEnableInboundLog && mInboundSizeSoFar < mLogSizeLimit && returnVal == inNumBytes ) { int numToLog = inNumBytes; if( mInboundSizeSoFar + numToLog > mLogSizeLimit ) { numToLog = mLogSizeLimit - mInboundSizeSoFar; } if( mInboundLogFile != NULL ) { fwrite( inBuffer, 1, numToLog, mInboundLogFile ); fflush( mInboundLogFile ); } mInboundSizeSoFar += numToLog; } return returnVal; } inline long LoggingSocketStream::write( unsigned char *inBuffer, long inNumBytes ) { long returnVal = SocketStream::write( inBuffer, inNumBytes ); if( mEnableOutboundLog && mOutboundSizeSoFar < mLogSizeLimit && returnVal == inNumBytes ) { int numToLog = inNumBytes; if( mOutboundSizeSoFar + numToLog > mLogSizeLimit ) { numToLog = mLogSizeLimit - mOutboundSizeSoFar; } if( mOutboundLogFile != NULL ) { fwrite( inBuffer, 1, numToLog, mOutboundLogFile ); fflush( mOutboundLogFile ); } mOutboundSizeSoFar += numToLog; } return returnVal; } #endif between-6+dfsg1.orig/minorGems/network/LookupThread.h0000640000175000017500000000272111435543335021454 0ustar pabspabs/* * Modification History * * 2008-October-21 Jason Rohrer * Created. * * 2009-February-3 Jason Rohrer * Changed to subclass FinishedSignalThread. * * 2009-February-14 Jason Rohrer * Changed to copy inAddress internally. */ #ifndef LOOKUP_THREAD_CLASS_INCLUDED #define LOOKUP_THREAD_CLASS_INCLUDED #include "minorGems/system/FinishedSignalThread.h" #include "minorGems/system/MutexLock.h" #include "minorGems/network/HostAddress.h" /** * Thread that performs DNS lookup on a host name. * * @author Jason Rohrer */ class LookupThread : public FinishedSignalThread { public: /** * Constructs and starts a lookup thread. * * @param inAddress the address to lookup. Destroyed by caller, * copied internally. */ LookupThread( HostAddress *inAddress ); // joins and destroys this thread ~LookupThread(); /** * Returns true if lookup done. */ char isLookupDone(); /** * Returns numerical address result, or NULL if lookup failed. * * Must be destroyed by caller if non-NULL. */ HostAddress *getResult(); // override the run method from Thread void run(); private: MutexLock mLock; HostAddress *mAddress; HostAddress *mNumericalAddress; char mLookupDone; }; #endif between-6+dfsg1.orig/minorGems/network/win32/0000750000175000017500000000000011435543336017642 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/network/win32/SocketWin32.cpp0000640000175000017500000002572711435543336022437 0ustar pabspabs/* * Modification History * * 2001-January-28 Jason Rohrer * Created. * * 2001-February-4 Jason Rohrer * Fixed receive so that it waits for all requested bytes to arrive. * * 2001-March-4 Jason Rohrer * Replaced include of and with * to fix compile bugs encountered with newer windows compilers. * * 2001-May-12 Jason Rohrer * Fixed a bug in socket receive error checking. * * 2001-November-13 Jason Rohrer * Changed timeout parameter to signed, since -1 is a possible argument. * * 2002-April-15 Jason Rohrer * Removed call to WSAGetLastError, since it seems to pick up errors from * non-socket calls. For example, if sys/stat.h stat() is called on a file * that does not exist, WSAGetLastError returns 2, which is not even a * winsock error code. We should probably report this bug, huh? * * 2002-August-2 Jason Rohrer * Added functon for getting remote host address, but no implementation. * * 2002-August-5 Jason Rohrer * Added implementation of getRemoteHostAddress(). * * 2002-September-8 Jason Rohrer * Fixed a major looping bug with broken sockets. * * 2002-November-15 Jason Rohrer * Fixed a security hole when getting the remote host address. * * 2003-February-4 Jason Rohrer * Added a function for getting the local host address from a socket. * Still need to test the win32 version of this. * * 2003-February-5 Jason Rohrer * Fixed a bug in call to gethostname. Removed unused variable. * * 2004-January-4 Jason Rohrer * Added use of network function locks. * * 2004-January-11 Jason Rohrer * Fixed a bug in handling of timeout return value. * * 2004-March-23 Jason Rohrer * Removed timeout error message. * * 2004-December-13 Jason Rohrer * Added a breakConnection function. * * 2004-December-24 Jason Rohrer * Fixed bug in close call. * * 2005-July-5 Jason Rohrer * Added port number when getting address of remote host. * * 2006-May-28 Jason Rohrer * Changed timeout behavior slightly to support emulation of non-blocking mode. * * 2006-June-5 Jason Rohrer * Added support for non-blocking sends. * * 2008-September-30 Jason Rohrer * Added support for non-blocking connect. * Fixed close-detection in non-blocking read. * * 2010-January-26 Jason Rohrer * Added support for disabling Nagle algorithm. */ #include "minorGems/network/Socket.h" #include "minorGems/network/NetworkFunctionLocks.h" #include #include #include #include #include // prototypes int timed_read( int inSock, unsigned char *inBuf, int inLen, long inMilliseconds ); /** * Windows-specific implementation of the Socket class member functions. * */ // Win32 does not define socklen_t typedef int socklen_t; char Socket::sInitialized = false; int Socket::initSocketFramework() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 0 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { // no usable DLL found printf( "WinSock DLL version 1.0 or higher not found.\n" ); return -1; } sInitialized = true; return 0; } Socket::~Socket() { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; if( !mIsConnectionBroken ) { // 2 specifies shutting down both sends and receives shutdown( socketID, 2 ); mIsConnectionBroken = true; } closesocket( socketID ); delete [] socketIDptr; } int Socket::isConnected() { if( mConnected ) { return 1; } int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; int ret; fd_set fsr; struct timeval tv; int val; socklen_t len; FD_ZERO( &fsr ); FD_SET( socketID, &fsr ); // check if connection event waiting right now // timeout of 0 tv.tv_sec = 0; tv.tv_usec = 0; ret = select( socketID + 1, NULL, &fsr, NULL, &tv ); if( ret==0 ) { // timeout return 0; } // no timeout // error? len = 4; ret = getsockopt( socketID, SOL_SOCKET, SO_ERROR, (char*)( &val ), &len ); if( ret < 0 ) { // error return -1; } if( val != 0 ) { // error return -1; } // success mConnected = true; return 1; } void Socket::setNoDelay( int inValue ) { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; int flag = inValue; int result = setsockopt( socketID, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int) ); } int Socket::send( unsigned char *inBuffer, int inNumBytes, char inAllowedToBlock, char inAllowDelay ) { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; if( inAllowedToBlock ) { if( ! inAllowDelay ) { // turn nodelay on setNoDelay( 1 ); } int returnVal = ::send( socketID, (char*)inBuffer, inNumBytes, 0 ); if( ! inAllowDelay ) { // turn nodelay back off setNoDelay( 0 ); } return returnVal; } else { // 1 for non-blocking, 0 for blocking u_long socketMode = 1; ioctlsocket( socketID, FIONBIO, &socketMode ); if( ! inAllowDelay ) { // turn nodelay on setNoDelay( 1 ); } int result = ::send( socketID, (char*)inBuffer, inNumBytes, 0 ); if( ! inAllowDelay ) { // turn nodelay back off setNoDelay( 0 ); } // set back to blocking socketMode = 0; ioctlsocket( socketID, FIONBIO, &socketMode ); if( result == -1 && WSAGetLastError() == WSAEWOULDBLOCK ) { return -2; } else { return result; } } } int Socket::receive( unsigned char *inBuffer, int inNumBytes, long inTimeout ) { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; int numReceived = 0; char error = false; char errorReturnValue = -1; char stopLooping = false; // for win32, we can't specify MSG_WAITALL // so we have too loop until the entire message is received, // as long as there is no error. // note that if a timeout is set, we use the stopLooping flag // to return only the available data (we do not emulate MSG_WAITALL) while( numReceived < inNumBytes && !error && !stopLooping ) { // the number of bytes left to receive int numRemaining = inNumBytes - numReceived; // pointer to the spot in the buffer where the // remaining bytes should be stored unsigned char *remainingBuffer = &( inBuffer[ numReceived ] ); int numReceivedIn; if( inTimeout == -1 ) { numReceivedIn = recv( socketID, (char*)remainingBuffer, numRemaining, 0 ); } else { numReceivedIn = timed_read( socketID, remainingBuffer, numRemaining, inTimeout ); // stop looping after one timed read stopLooping = true; } if( numReceivedIn > 0 ) { numReceived += numReceivedIn; } else { error = true; if( numReceivedIn == 0 ) { // the socket was gracefully closed errorReturnValue = -1; } else if( numReceivedIn == SOCKET_ERROR ) { // socket error errorReturnValue = -1; } else if( numReceivedIn == -2 ) { // timeout errorReturnValue = -2; } else { printf( "Unexpected return value from socket receive: %d.\n", numReceivedIn ); errorReturnValue = -1; } } } if( error ) { return errorReturnValue; } else { return numReceived; } } void Socket::breakConnection() { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; if( !mIsConnectionBroken ) { shutdown( socketID, 2 ); mIsConnectionBroken = true; } closesocket( socketID ); } HostAddress *Socket::getRemoteHostAddress() { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; // adapted from Unix Socket FAQ socklen_t len; struct sockaddr_in sin; len = sizeof sin; int error = getpeername( socketID, (struct sockaddr *) &sin, &len ); if( error ) { return NULL; } // this is potentially insecure, since a fake DNS name might be returned // we should use the IP address only // // struct hostent *host = gethostbyaddr( (char *) &sin.sin_addr, // sizeof sin.sin_addr, // AF_INET ); NetworkFunctionLocks::mInet_ntoaLock.lock(); // returned string is statically allocated, copy it char *ipAddress = stringDuplicate( inet_ntoa( sin.sin_addr ) ); NetworkFunctionLocks::mInet_ntoaLock.unlock(); int port = ntohs( sin.sin_port ); return new HostAddress( ipAddress, port ); } HostAddress *Socket::getLocalHostAddress() { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; // adapted from GTK-gnutalla code, and elsewhere struct sockaddr_in addr; int len = sizeof( struct sockaddr_in ); int result = getsockname( socketID, (struct sockaddr*)( &addr ), &len ); if( result == -1 ) { return NULL; } else { char *stringAddress = inet_ntoa( addr.sin_addr ); return new HostAddress( stringDuplicate( stringAddress ), 0 ); } } /* timed_read adapted from gnut, by Josh Pieper */ /* Josh Pieper, (c) 2000 */ /* This file is distributed under the GPL, see file COPYING for details */ // exactly like the real read, except that it returns -2 // if no data was read before the timeout occurred... int timed_read( int inSock, unsigned char *inBuf, int inLen, long inMilliseconds ) { fd_set fsr; struct timeval tv; int ret; FD_ZERO( &fsr ); FD_SET( inSock, &fsr ); tv.tv_sec = inMilliseconds / 1000; int remainder = inMilliseconds % 1000; tv.tv_usec = remainder * 1000; ret = select( inSock + 1, &fsr, NULL, NULL, &tv ); if( ret==0 ) { // printf( "Timed out waiting for data on socket receive.\n" ); return -2; } if( ret<0 ) { printf( "Selecting socket during receive failed.\n" ); return ret; } ret = recv( inSock, (char*)inBuf, inLen, 0 ); if( ret == 0 ) { // select came back as 1, but no data there // connection closed on remote end return -1; } return ret; } between-6+dfsg1.orig/minorGems/network/win32/HostAddressWin32.cpp0000640000175000017500000000715111435543336023421 0ustar pabspabs/* * Modification History * * 2001-December-14 Jason Rohrer * Created. * Has not been compiled or tested under windows. * * 2002-March-25 Jason Rohrer * Added function for conversion to numerical addresses. * * 2002-March-26 Jason Rohrer * Changed to use strdup. * Fixed problem on some platforms where local address does * not include domain name. * Fixed so that numerical address is actually retrieved by * getNumericalAddress(). * * 2002-April-6 Jason Rohrer * Replaced use of strdup. * * 2002-April-7 Jason Rohrer * Changed to return numerical address from getLocalAddress, * since getdomainname() call not available on Win32. * * 2002-April-8 Jason Rohrer * Changed to init socket framework before getting local address. * Changed to check if address is numerical before * performing a lookup on it. * * 2004-January-4 Jason Rohrer * Added use of network function locks. * * 2008-November-2 Jason Rohrer * Added framework init in getNumericalAddress. */ #include "minorGems/network/HostAddress.h" #include "minorGems/network/NetworkFunctionLocks.h" #include "minorGems/util/stringUtils.h" #include #include #include #include "minorGems/network/Socket.h" HostAddress *HostAddress::getLocalAddress() { // first make sure sockets are initialized if( !Socket::isFrameworkInitialized() ) { // try to init the framework int error = Socket::initSocketFramework(); if( error == -1 ) { printf( "initializing network socket framework failed\n" ); return NULL; } } int bufferLength = 200; char *buffer = new char[ bufferLength ]; gethostname( buffer, bufferLength ); char *name = stringDuplicate( buffer ); delete [] buffer; // this class will destroy name for us HostAddress *nameAddress = new HostAddress( name, 0 ); HostAddress *fullAddress = nameAddress->getNumericalAddress(); delete nameAddress; return fullAddress; } HostAddress *HostAddress::getNumericalAddress() { // make sure we're not already numerical if( this->isNumerical() ) { return this->copy(); } if( !Socket::isFrameworkInitialized() ) { // try to init the framework int error = Socket::initSocketFramework(); if( error == -1 ) { printf( "initializing network socket framework failed\n" ); return NULL; } } // need to use two function locks here // first, lock for gethostbyname NetworkFunctionLocks::mGetHostByNameLock.lock(); struct hostent *host = gethostbyname( mAddressString ); if (host != NULL) { // this line adapted from the // Unix Socket FAQ struct in_addr *inetAddress = (struct in_addr *) *host->h_addr_list; // now lock for inet_ntoa NetworkFunctionLocks::mInet_ntoaLock.lock(); // the returned string is statically allocated, so copy it char *inetAddressString = stringDuplicate( inet_ntoa( *inetAddress ) ); NetworkFunctionLocks::mInet_ntoaLock.unlock(); // done with returned hostent now, so unlock first lock NetworkFunctionLocks::mGetHostByNameLock.unlock(); return new HostAddress( inetAddressString, mPort ); } else { // unlock first lock before returning NetworkFunctionLocks::mGetHostByNameLock.unlock(); return NULL; } } char HostAddress::isNumerical() { unsigned long returnedValue = inet_addr( mAddressString ); if( returnedValue == INADDR_NONE ) { return false; } else { return true; } } between-6+dfsg1.orig/minorGems/network/win32/SocketClientWin32.cpp0000640000175000017500000001724311435543336023570 0ustar pabspabs/* * Modification History * * 2001-January-28 Jason Rohrer * Created. * * 2001-January-29 Jason Rohrer * Fixed an endian bug that was messing up the port numbers. * * 2002-October-13 Jason Rohrer * Added support for timeout on connect. * Fixed several windows compile bugs. * * 2002-December-2 Jason Rohrer * Fixed resource leak when connection fails. * Changed close calls to win32 closesocket calls. * * 2004-January-2 Jason Rohrer * Fixed a thread safety issue with gethostbyname. * * 2004-January-4 Jason Rohrer * Added use of network function locks. * * 2006-April-25 Jason Rohrer * Added missing check for a NULL outTimedOut parameter. * * 2008-September-30 Jason Rohrer * Added support for non-blocking connect. * * 2009-October-5 Jason Rohrer * Fixed bug when connect timeout not used. */ #include "minorGems/network/SocketClient.h" #include "minorGems/network/NetworkFunctionLocks.h" #include "minorGems/system/MutexLock.h" #include #include #include #include #include // prototypes struct in_addr *nameToAddress( char *inAddress ); int timed_connect( int inSocketID, struct sockaddr *inSocketAddress, int inAddressLength, int inTimeoutInMilliseconds ); Socket *SocketClient::connectToServer( HostAddress *inAddress, long inTimeoutInMilliseconds, char *outTimedOut ) { if( !Socket::isFrameworkInitialized() ) { // try to init the framework int error = Socket::initSocketFramework(); if( error == -1 ) { printf( "initializing network socket framework failed\n" ); return NULL; } } unsigned long socketID = socket( AF_INET, SOCK_STREAM, 0 ); if( socketID == INVALID_SOCKET ) { printf( "Creating socket failed.\n" ); return NULL; } union sock { struct sockaddr s; struct sockaddr_in i; } sock; //struct in_addr internet_address; //struct hostent *hp; struct in_addr *internet_address = nameToAddress( inAddress->mAddressString ); if( internet_address == NULL ) { printf( "Host name lookup failed: " ); inAddress->print(); printf( "\n" ); closesocket( socketID ); return NULL; } //hp = gethostbyname( inAddress->mAddressString ); //memcpy( &internet_address, *( hp->h_addr_list ), sizeof( struct in_addr ) ); sock.i.sin_family = AF_INET; sock.i.sin_port = htons( inAddress->mPort ); sock.i.sin_addr = *internet_address; int error; if( inTimeoutInMilliseconds != -1 ) { // use timeout error = timed_connect( socketID, &sock.s, sizeof( struct sockaddr ), inTimeoutInMilliseconds ); if( outTimedOut != NULL ) { if( error == -2 ) { *outTimedOut = true; if( inTimeoutInMilliseconds == 0 ) { // caller didn't want to wait at all error = 0; } else { // treat timeout as error error = -1; } } else { *outTimedOut = false; } } } else { // don't use timeout error = connect( socketID, &sock.s, sizeof( struct sockaddr ) ); } delete internet_address; if( error == -1 ) { //printf( "Connecting to host failed: " ); //inAddress->print(); //printf( "\n" ); closesocket( socketID ); return NULL; } // package into a Socket and return it Socket *returnSocket = new Socket(); unsigned long *idSpace = new unsigned long[1]; idSpace[0] = socketID; returnSocket->mNativeObjectPointer = (void *)idSpace; if( outTimedOut != NULL && *outTimedOut ) { // not connected yet returnSocket->setConnected( false ); } return returnSocket; } /* Converts ascii text to in_addr struct. NULL is returned if the address can not be found. Result must be destroyed by caller. Adapted from the Unix Socket FAQ */ struct in_addr *nameToAddress( char *inAddress ) { struct hostent *host; static struct in_addr saddr; struct in_addr *copiedSaddr = new struct in_addr; /* First try it as aaa.bbb.ccc.ddd. */ saddr.s_addr = inet_addr( inAddress ); if( saddr.s_addr != INADDR_NONE ) { // copy to avoid returning pointer to stack memcpy( copiedSaddr, &saddr, sizeof( struct in_addr ) ); return copiedSaddr; } // must keep this locked until we are done copying the in_addr out // of the returned hostent NetworkFunctionLocks::mGetHostByNameLock.lock(); char hostFound = false; host = gethostbyname( inAddress ); if( host != NULL ) { memcpy( copiedSaddr, *host->h_addr_list, sizeof( struct in_addr ) ); hostFound = true; } NetworkFunctionLocks::mGetHostByNameLock.unlock(); if( hostFound ) { return copiedSaddr; } else { delete copiedSaddr; } return NULL; } /* timed_read adapted from gnut, by Josh Pieper */ /* Josh Pieper, (c) 2000 */ /* This file is distributed under the GPL, see file COPYING for details */ // just like connect except that it times out after time secs // returns -2 on timeout, otherwise same as connect int timed_connect( int inSocketID, struct sockaddr *inSocketAddress, int inAddressLength, int inTimeoutInMilliseconds ) { int ret; fd_set fsr; struct timeval tv; int val; int len; //g_debug(1,"entering sock=%i secs=%i\n",inSocketID,inTimeoutInSeconds); //ret = fcntl( inSocketID, F_SETFL, O_NONBLOCK ); // use ioctlsocket on win32 instead of fcntl // set to non-blocking mode unsigned long onFlag = 1; ret = ioctlsocket( inSocketID, FIONBIO, &onFlag ); //g_debug(5,"fcntl returned %i\n",ret); if( ret < 0 ) { return ret; } ret = connect( inSocketID, inSocketAddress, inAddressLength ); //g_debug(5,"connect returned %i\n",ret); if( ret == 0 ) { //g_debug(0,"immediate connection!\n"); // wooah! immediate connection // return -2; // changed from what Josh originally returned (-2) // immediate connection *can* happen sometimes, right? // for example, when connecting to localhost... return 0; } // if (errno != EINPROGRESS) { // perror("timed_connect, connect"); // return ret; // } FD_ZERO( &fsr ); FD_SET( inSocketID, &fsr ); tv.tv_sec = inTimeoutInMilliseconds / 1000; int remainder = inTimeoutInMilliseconds % 1000; tv.tv_usec = remainder * 1000; ret = select( inSocketID+1, NULL, &fsr, NULL, &tv ); //g_debug(5,"select returned %i\n",ret); if( ret==0 ) { // timeout //g_debug(1,"timeout\n"); //fcntl( inSocketID, F_SETFL, 0 ); unsigned long offFlag = 0; ret = ioctlsocket( inSocketID, FIONBIO, &offFlag ); return -2; } len = 4; ret = getsockopt( inSocketID, SOL_SOCKET, SO_ERROR, (char*)( &val ), &len ); //g_debug(5,"getsockopt returned %i val=%i\n",ret,val); if( ret < 0 ) { //g_debug(1,"getsockopt returned: %i\n",ret); return ret; } if (val!=0) { //g_debug(3,"returning failure!\n"); return -1; } //ret = fcntl( inSocketID, F_SETFL, 0 ); // use ioctlsocket on win32 instead of fcntl // set back to blocking mode unsigned long offFlag = 0; ret = ioctlsocket( inSocketID, FIONBIO, &offFlag ); //g_debug(1,"fcntl: %i\n",ret); //g_debug(3,"returning success val=%i\n",val); return 0; } between-6+dfsg1.orig/minorGems/network/win32/WSABugDemo.cpp0000640000175000017500000000140211435543336022241 0ustar pabspabs#include #include #include #include int main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 0 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { // no usable DLL found printf( "WinSock DLL version 1.0 or higher not found.\n" ); return -1; } int error = WSAGetLastError(); printf( "WSA Error before stat call = %d\n", error ); struct stat fileInfo; int statError = stat( "DoesNotExist", &fileInfo ); printf( "stat error = %d\n", statError ); error = WSAGetLastError(); printf( "WSA Error after stat call = %d\n", error ); return 0; } between-6+dfsg1.orig/minorGems/network/win32/SocketServerWin32.cpp0000640000175000017500000000762711435543336023625 0ustar pabspabs/* * Modification History * * 2001-January-28 Jason Rohrer * Created. * * 2001-January-29 Jason Rohrer * Fixed an endian bug that was messing up the port numbers. * * 2002-April-6 Jason Rohrer * Changed to implement the new timeout-on-accept interface, * though did no actually implement timeouts. * * 2002-September-8 Jason Rohrer * Added a check for a potentially NULL argument. * * 2004-February-23 Jason Rohrer * Added timeout code for accepting connections. * Removed use of shutdown on listening socket. */ #include "minorGems/network/SocketServer.h" #include #include union sock { struct sockaddr s; struct sockaddr_in i; } sock; SocketServer::SocketServer( int inPort, int inMaxQueuedConnections ) { int error = 0; if( !Socket::isFrameworkInitialized() ) { // try to init the framework int error = Socket::initSocketFramework(); if( error == -1 ) { printf( "initializing network socket framework failed\n" ); exit( 1 ); } } // create the socket int sockID = socket( AF_INET, SOCK_STREAM, 0 ); if( sockID == INVALID_SOCKET ) { printf( "Creating socket failed.\n" ); exit( 1 ); } // store socket id in native object pointer int *idStorage = new int[1]; idStorage[0] = sockID; mNativeObjectPointer = (void *)idStorage; // bind socket to the port union sock sockAddress; sockAddress.i.sin_family = AF_INET; sockAddress.i.sin_port = htons( inPort ); sockAddress.i.sin_addr.s_addr = INADDR_ANY; error = bind( sockID, &(sockAddress.s), sizeof( struct sockaddr ) ); if( error == -1 ) { printf( "Network socket bind to port %d failed\n", inPort ); exit( 1 ); } // start listening for connections error = listen( sockID, inMaxQueuedConnections ); if( error == -1 ) { printf( "Listening for network socket connections failed.\n" ); exit(1); } } SocketServer::~SocketServer() { int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; closesocket( socketID ); delete [] socketIDptr; } Socket *SocketServer::acceptConnection( long inTimeoutInMilliseconds, char *outTimedOut ) { if( outTimedOut != NULL ) { *outTimedOut = false; } // printf( "Waiting for a connection.\n" ); // extract socket id from native object pointer int *socketIDptr = (int *)( mNativeObjectPointer ); int socketID = socketIDptr[0]; // same timeout code as in linux version if( inTimeoutInMilliseconds != -1 ) { // if we have a timeout specified, select before accepting // this found in the Linux man page for select, // but idea (which originally used poll) was found // in the Unix Socket FAQ fd_set rfds; struct timeval tv; int retval; // insert our socket descriptor into this set FD_ZERO( &rfds ); FD_SET( socketID, &rfds ); // convert our timeout into the structure's format tv.tv_sec = inTimeoutInMilliseconds / 1000; tv.tv_usec = ( inTimeoutInMilliseconds % 1000 ) * 1000 ; retval = select( socketID + 1, &rfds, NULL, NULL, &tv ); if( retval == 0 ) { // timeout if( outTimedOut != NULL ) { *outTimedOut = true; } return NULL; } } //int addressLength; //union sock acceptedAddress; struct sockaddr acceptedAddress; //int addressLength = sizeof( struct sockaddr ); int acceptedID = accept( socketID, &( acceptedAddress ), NULL ); if( acceptedID == -1 ) { printf( "Failed to accept a network connection.\n" ); return NULL; } Socket *acceptedSocket = new Socket(); int *idStorage = new int[1]; idStorage[0] = acceptedID; acceptedSocket->mNativeObjectPointer = (void *)idStorage; //printf( "Connection received.\n" ); return acceptedSocket; } between-6+dfsg1.orig/minorGems/network/SocketStream.h0000640000175000017500000000712511435543336021463 0ustar pabspabs/* * Modification History * * 2001-January-10 Jason Rohrer * Created. * * 2001-January-15 Jason Rohrer * Changed so that underlying socket is not destroyed when the stream * is destroyed. Updated to match new Stream interface, which uses longs * instead of ints. * * 2001-February-21 Jason Rohrer * Changed to set stream error messages on socket errors. * * 2002-July-31 Jason Rohrer * Added fix for partial sends. * * 2003-August-12 Jason Rohrer * Added support for read timeouts. * * 2004-January-27 Jason Rohrer * Made functions virtual to support subclassing. */ #include "minorGems/common.h" #ifndef SOCKET_STREAM_CLASS_INCLUDED #define SOCKET_STREAM_CLASS_INCLUDED #include "Socket.h" #include "minorGems/io/InputStream.h" #include "minorGems/io/OutputStream.h" /** * A input and output stream interface for a network socket. * * @author Jason Rohrer */ class SocketStream : public InputStream, public OutputStream { public: /** * Constructs a SocketStream. * * @param inSocket the newtork socket wrapped by this stream. * inSocket is NOT destroyed when the stream is destroyed. */ SocketStream( Socket *inSocket ); // a virtual destructor to ensure that subclass destructors are called virtual ~SocketStream(); /** * Sets the timeout for reads on this socket. * * The timeout defaults to -1 (no timeout). * * @param inMilliseconds the timeout in milliseconds, * or -1 to specify no timeout. */ void setReadTimeout( long inMilliseconds ); /** * Gets the timeout for reads on this socket. * * @return the timeout in milliseconds, * or -1 to indicate no timeout. */ long getReadTimeout(); // implements the InputStream interface. // virtual to allow subclasses to override // in addition, -2 is returned if the read times out. virtual long read( unsigned char *inBuffer, long inNumBytes ); // implements the OutputStream interface virtual long write( unsigned char *inBuffer, long inNumBytes ); protected: Socket *mSocket; long mReadTimeout; }; inline SocketStream::SocketStream( Socket *inSocket ) : mSocket( inSocket ), mReadTimeout( -1 ) { } inline SocketStream::~SocketStream() { // does nothing // exists only to allow for subclass destructors } inline void SocketStream::setReadTimeout( long inMilliseconds ) { mReadTimeout = inMilliseconds; } inline long SocketStream::getReadTimeout() { return mReadTimeout; } inline long SocketStream::read( unsigned char *inBuffer, long inNumBytes ) { int numReceived = mSocket->receive( inBuffer, inNumBytes, mReadTimeout ); if( numReceived == -1 ) { // socket error InputStream::setNewLastErrorConst( "Network socket error on receive." ); } return numReceived; } inline long SocketStream::write( unsigned char *inBuffer, long inNumBytes ) { long numTotalSent = 0; while( numTotalSent < inNumBytes ) { unsigned char *partialBuffer = &( inBuffer[numTotalSent] ); int numRemaining = inNumBytes - numTotalSent; int numSent = mSocket->send( partialBuffer, numRemaining ); if( numSent == -1 || numSent == 0 ) { // socket error OutputStream::setNewLastErrorConst( "Network socket error on send." ); return -1; } numTotalSent += numSent; } return numTotalSent; } #endif between-6+dfsg1.orig/minorGems/network/Message.h0000640000175000017500000000162511435543335020441 0ustar pabspabs/* * Modification History * * 2001-January-15 Jason Rohrer * Created. * * 2001-February-3 Jason Rohrer * Updated serialization code to use new interfaces. */ #include "minorGems/common.h" #ifndef MESSAGE_CLASS_INCLUDED #define MESSAGE_CLASS_INCLUDED #include "minorGems/io/Serializable.h" /** * A simple message that carries a 4 byte opcode. Useful for sending a * simple service request. * * @author Jason Rohrer */ class Message : public Serializable { public: long mOpcode; // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); }; inline int Message::serialize( OutputStream *inOutputStream ) { return inOutputStream->writeLong( mOpcode ); } inline int Message::deserialize( InputStream *inInputStream ) { return inInputStream->readLong( &mOpcode ); } #endif between-6+dfsg1.orig/minorGems/.hg_archival.txt0000640000175000017500000000024111435543333020270 0ustar pabspabsrepo: 6e2a2a18b9d8455339d0b3230b832d565b1ee56e node: 4c43066eeb56611c7c1c0dd46ab0451451fbe7db branch: default latesttag: SleepIsDeath_v15b latesttagdistance: 14 between-6+dfsg1.orig/minorGems/math/0000750000175000017500000000000011435543335016137 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/math/BigInt.h0000640000175000017500000001045711435543335017474 0ustar pabspabs/* * Modification History * * 2002-May-25 Jason Rohrer * Created. * Made getZero static. */ #ifndef BIG_INT_INCLUDED #define BIG_INT_INCLUDED /** * A multi-byte integer representation. * * Some of the ideas used in this class were gleaned * from studying Sun's Java 1.3 BigInteger implementation. * * @author Jason Rohrer. */ class BigInt { public: /** * Constructs an integer. * * @param inSign the sign of this integer: * -1 if negative, +1 if positive, and 0 if zero. * @param inNumBytes the number of bytes in this integer. * @param inBytes the bytes for this integer. * Copied internally, so must be destroyed by caller. */ BigInt( int inSign, int inNumBytes, unsigned char *inBytes ); /** * Constructs an integer from a 32-bit int. * * @param inInt the int to use. */ BigInt( int inInt ); ~BigInt(); /** * Adds an integer to this integer. * * @praram inOtherInt the int to add. * Must be destroyed by caller. * * @return a newly allocated integer containing the sum. * Must be destroyed by caller. */ BigInt *add( BigInt *inOtherInt ); /** * Subtracts an integer from this integer. * * @praram inOtherInt the int to subtract. * Must be destroyed by caller. * * @return a newly allocated integer containing the difference. * Must be destroyed by caller. */ BigInt *subtract( BigInt *inOtherInt ); /** * Gets whether this integer is less than another integer. * * @praram inOtherInt the integer test. * Must be destroyed by caller. * * @return true if this integer is less than the other. */ char isLessThan( BigInt *inOtherInt ); /** * Gets whether this integer is equal to another integer. * * @praram inOtherInt the integer test. * Must be destroyed by caller. * * @return true if this integer is equal to the other. */ char isEqualTo( BigInt *inOtherInt ); /** * Gets a copy of this integer. * * @return a newly allocated integer containing the copy. * Must be destroyed by caller. */ BigInt *copy(); /** * Gets an integer equal to zero. * * @return a newly allocated integer containing zero. * Must be destroyed by caller. */ static BigInt *getZero(); /** * Converts this integer to a decimal string. * * @return a \0-terminated ascii decimal string. * Must be destroyed by caller. */ //char *convertToDecimalString(); /** * Converts this integer to a hex string. * * @return a \0-terminated ascii hexx string. * Must be destroyed by caller. */ char *convertToHexString(); /** * Converts this integer to a 32-bit int. * * If this integer contains more than 32-bits, the high-order * bits will be discarded, though the sign will be preserved. */ int convertToInt(); /** * -1 if negative, +1 if positive, and 0 if zero. */ int mSign; int mNumBytes; /** * Integer is stored in big endian byte order. */ unsigned char *mBytes; protected: /** * Flips the byte order of this integer. * * @return a newly allocated integer containing the flipped version. * Must be destroyed by caller. */ BigInt *flipByteOrder(); /** * Computes the hex representation of a four-bit int. * * @param inInt the four-bit int to convert. * * @return the int as a hex ascii character, * in {0, 1, ..., A, B, ..., F}. */ char fourBitIntToHex( int inInt ); }; #endif between-6+dfsg1.orig/minorGems/math/stats/0000750000175000017500000000000011435543335017275 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/math/stats/PairwiseOrderingErrorEvaluator.h0000640000175000017500000000237011435543335025623 0ustar pabspabs/* * Modification History * * 2000-September-28 Jason Rohrer * Created. */ #ifndef PAIRWISE_ORDERING_ERROR_EVALUATOR_INCLUDED #define PAIRWISE_ORDERING_ERROR_EVALUATOR_INCLUDED #include "ErrorEvaluator.h" /** * Implementation of ErrorEvaluator that generates an error * value based on the number of pairs of elements in the * the test vector that are not given the same order by their values * as are the corresponding pair of values in the correct vector. * * I.e., if A[i] > A[j], then B[i] < B[j] adds 1 to the error term, * while B[i] > B[j] adds 0 to the error term. * * @author Jason Rohrer */ class PairwiseOrderingErrorEvaluator : public ErrorEvaluator { // implements ErrorEvaluator interface double evaluate( double *inVectorA, double *inVectorB, int inLength ); }; inline double PairwiseOrderingErrorEvaluator::evaluate( double *inVectorA, double *inVectorB, int inLength ) { double sum = 0; // examine all pairs of components in the vectors for( int i=0; i inVectorA[j] && inVectorB[i] <= inVectorB[j] ) || ( inVectorA[i] < inVectorA[j] && inVectorB[i] >= inVectorB[j] ) ) { sum++; } } } return sum; } #endif between-6+dfsg1.orig/minorGems/math/stats/ErrorEvaluator.h0000640000175000017500000000131111435543335022417 0ustar pabspabs/* * Modification History * * 2000-September-28 Jason Rohrer * Created. */ #ifndef ERROR_EVALUATOR_INCLUDED #define ERROR_EVALUATOR_INCLUDED /** * Interface for a class that evaluates a vector against another * to produce a scalar error value. * * @author Jason Rohrer */ class ErrorEvaluator { public: /** * Evaluates two input vectors to produce an output error value. * * @param inVectorA the first vector (the actual, or "correct" value) * @param inVectorB the second vector ( the predicted, or "test" value) * * @return the error value between the two vectors */ virtual double evaluate( double *inVectorA, double *inVectorB, int inLength ) = 0; }; #endif between-6+dfsg1.orig/minorGems/math/stats/L1ErrorEvaluator.h0000640000175000017500000000134411435543335022622 0ustar pabspabs/* * Modification History * * 2000-September-28 Jason Rohrer * Created. */ #ifndef L1_ERROR_EVALUATOR_INCLUDED #define L1_ERROR_EVALUATOR_INCLUDED #include "ErrorEvaluator.h" /** * L1 distance implementation of ErrorEvaluator. * * @author Jason Rohrer */ class L1ErrorEvaluator : public ErrorEvaluator { public: // implements ErrorEvaluator interface double evaluate( double *inVectorA, double *inVectorB, int inLength ); }; inline double L1ErrorEvaluator::evaluate( double *inVectorA, double *inVectorB, int inLength ) { double sum = 0; for( int i=0; ievaluate() ); } long InvertExpression::getID() { return mID; } inline long InvertExpression::staticGetID() { return mID; } inline void InvertExpression::print() { printf( "( 1/" ); mArgument->print(); printf( " )" ); } inline Expression *InvertExpression::copy() { InvertExpression *copy = new InvertExpression( mArgument->copy() ); return copy; } #endif between-6+dfsg1.orig/minorGems/math/expression/BinaryLogicExpression.h0000640000175000017500000001064111435543335024774 0ustar pabspabs/* * Modification History * * 2003-May-2 Jason Rohrer * Created. * * 2003-May-3 Jason Rohrer * Fixed a few compile-time errors. */ #ifndef BINARY_LOGIC_EXPRESSION_INCLUDED #define BINARY_LOGIC_EXPRESSION_INCLUDED #include "Expression.h" #include "BinaryOperationExpression.h" /** * Expression implementation of a binary logic operation. * * Evaluating this expression returns 1 if the logic operation is true * and 0 if it is false. * * During evaluation, positive values are treated as logical true, * while all other values (zero and negative) are treated as false. * * @author Jason Rohrer */ class BinaryLogicExpression : public BinaryOperationExpression { public: static const int LOGIC_AND = 0; static const int LOGIC_OR = 1; static const int LOGIC_XOR = 2; /** * Constructs a binary logic operation expression. * * Both arguments are destroyed when the class is destroyed. * * @param inLogicOperation the logical operation, one of * LOGIC_AND, LOGIC_OR, LOGIC_XOR. * @param inArgumentA the first argument. * @param inArgumentB the second argument. */ BinaryLogicExpression( int inLogicOperation, Expression *inArgumentA, Expression *inArgumentB ); /** * Gets the logical operation. * * @return one of LOGIC_AND, LOGIC_OR, LOGIC_XOR. */ int getLogicOperation(); /** * Sets the logical operation * * @param inLogicOperation LOGIC_AND, LOGIC_OR, LOGIC_XOR. */ void setLogicOperation( int inLogicOperation ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; int mLogicOperation; }; // static init long BinaryLogicExpression::mID = 16; inline BinaryLogicExpression::BinaryLogicExpression( int inLogicOperation, Expression *inArgumentA, Expression *inArgumentB ) : BinaryOperationExpression( inArgumentA, inArgumentB ), mLogicOperation( inLogicOperation ) { } inline int BinaryLogicExpression::getLogicOperation() { return mLogicOperation; } inline void BinaryLogicExpression::setLogicOperation( int inLogicOperation ) { mLogicOperation = inLogicOperation; } inline double BinaryLogicExpression::evaluate() { if( mLogicOperation == LOGIC_AND ) { if( mArgumentA->evaluate() > 0 && mArgumentB->evaluate() > 0 ) { return 1; } else { return 0; } } else if( mLogicOperation == LOGIC_OR ) { if( mArgumentA->evaluate() > 0 || mArgumentB->evaluate() > 0 ) { return 1; } else { return 0; } } else if( mLogicOperation == LOGIC_XOR ) { double valA = mArgumentA->evaluate(); double valB = mArgumentB->evaluate(); if( ( valA > 0 && valB <= 0 ) || ( valA <= 0 && valB > 0 ) ) { return 1; } else { return 0; } } else { // unknown operation type // default to false return 0; } } inline long BinaryLogicExpression::getID() { return mID; } inline long BinaryLogicExpression::staticGetID() { return mID; } inline void BinaryLogicExpression::print() { printf( "( " ); mArgumentA->print(); if( mLogicOperation == LOGIC_AND ) { printf( " and " ); } else if( mLogicOperation == LOGIC_OR ) { printf( " or " ); } else if( mLogicOperation == LOGIC_XOR ) { printf( " xor " ); } else { printf( " UNKNOWN_LOGIC_OPERATION " ); } mArgumentB->print(); printf( " )" ); } inline Expression *BinaryLogicExpression::copy() { BinaryLogicExpression *copy = new BinaryLogicExpression( mLogicOperation, mArgumentA->copy(), mArgumentB->copy() ); return copy; } #endif between-6+dfsg1.orig/minorGems/math/expression/ConstantExpression.h0000640000175000017500000000473611435543335024373 0ustar pabspabs/* * Modification History * * 2001-February-11 Jason Rohrer * Created. * * 2001-March-10 Jason Rohrer * Added implementation of copy function. * * 2001-September-9 Jason Rohrer * Added an extractArgument() implemenation. */ #ifndef CONSTANT_EXPRESSION_INCLUDED #define CONSTANT_EXPRESSION_INCLUDED #include "Expression.h" /** * Expression implementation of a constant. * * @author Jason Rohrer */ class ConstantExpression : public Expression { public: /** * Constructs a constant expression. * * @param inValue the constant value. */ ConstantExpression( double inValue ); /** * Sets the constant value. * * @param inValue the constant value. */ void setValue( double inValue ); /** * Gets the constant value. * * @return the constant value. */ double getValue(); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getNumArguments(); virtual long getID(); virtual Expression *copy(); virtual Expression *getArgument( long inArgumentNumber ); virtual void setArgument( long inArgumentNumber, Expression *inArgument ); virtual Expression *extractArgument( long inArgumentNumber ); virtual void print(); protected: double mValue; static long mID; }; // static init long ConstantExpression::mID = 1; inline ConstantExpression::ConstantExpression( double inValue ) : mValue( inValue ) { } inline void ConstantExpression::setValue( double inValue ) { mValue = inValue; } inline double ConstantExpression::getValue() { return mValue; } inline double ConstantExpression::evaluate() { return mValue; } long ConstantExpression::getNumArguments() { return 0; } inline long ConstantExpression::getID() { return mID; } inline Expression *ConstantExpression::getArgument( long inArgumentNumber ) { return NULL; } inline void ConstantExpression::setArgument( long inArgumentNumber, Expression *inArgument ) { // do nothing return; } inline Expression *ConstantExpression::extractArgument( long inArgumentNumber ) { return NULL; } inline Expression *ConstantExpression::copy() { ConstantExpression *copy = new ConstantExpression( mValue ); return copy; } inline long ConstantExpression::staticGetID() { return mID; } inline void ConstantExpression::print() { printf( "( %f )", mValue ); } #endif between-6+dfsg1.orig/minorGems/math/expression/SumExpression.h0000640000175000017500000000337211435543335023341 0ustar pabspabs/* * Modification History * * 2001-February-10 Jason Rohrer * Created. * * 2001-March-10 Jason Rohrer * Added implementation of copy function. */ #ifndef SUM_EXPRESSION_INCLUDED #define SUM_EXPRESSION_INCLUDED #include "Expression.h" #include "BinaryOperationExpression.h" /** * Expression implementation of a binary sum operation. * * @author Jason Rohrer */ class SumExpression : public BinaryOperationExpression { public: /** * Constructs a binary sum operation expression. * * Both arguments are destroyed when the class is destroyed. * * @param inArgumentA the first argument. * @param inArgumentB the second argument. */ SumExpression( Expression *inArgumentA, Expression *inArgumentB ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; }; // static init long SumExpression::mID = 7; inline SumExpression::SumExpression( Expression *inArgumentA, Expression *inArgumentB ) : BinaryOperationExpression( inArgumentA, inArgumentB ) { } inline double SumExpression::evaluate() { return mArgumentA->evaluate() + mArgumentB->evaluate(); } inline long SumExpression::getID() { return mID; } inline long SumExpression::staticGetID() { return mID; } inline void SumExpression::print() { printf( "( " ); mArgumentA->print(); printf( " + " ); mArgumentB->print(); printf( " )" ); } inline Expression *SumExpression::copy() { SumExpression *copy = new SumExpression( mArgumentA->copy(), mArgumentB->copy() ); return copy; } #endif between-6+dfsg1.orig/minorGems/math/expression/Variable.h0000640000175000017500000000332611435543335022241 0ustar pabspabs/* * Modification History * * 2003-April-28 Jason Rohrer * Created. * * 2003-April-29 Jason Rohrer * Added missing destructor. */ #ifndef VARIABLE_INCLUDED #define VARIABLE_INCLUDED #include "minorGems/util/stringUtils.h" /** * Wrapper for a variable value. * * @author Jason Rohrer */ class Variable { public: /** * Constructs a variable, setting its value. * * @param inName the name of the variable. * Must be destroyed by caller if non-const. * @param inValue the initial value of the variable. */ Variable( char *inName, double inValue ); virtual ~Variable(); /** * Gets the value of this variable. * * @return the variable's value. */ virtual double getValue(); /** * Sets the value for this variable. * * @param inValue the value. */ virtual void setValue( double inValue ); /** * Gets the name of this variable. * * @return the name. * Must be destroyed by caller. */ virtual char *getName(); protected: char *mName; double mValue; }; inline Variable::Variable( char *inName, double inValue ) : mName( stringDuplicate( inName ) ), mValue( inValue ) { } inline Variable::~Variable() { delete [] mName; } inline double Variable::getValue() { return mValue; } inline void Variable::setValue( double inValue ) { mValue = inValue; } inline char *Variable::getName() { return stringDuplicate( mName ); } #endif between-6+dfsg1.orig/minorGems/math/expression/ComparisonExpression.h0000640000175000017500000001246411435543335024711 0ustar pabspabs/* * Modification History * * 2003-May-2 Jason Rohrer * Created. */ #ifndef COMPARISON_EXPRESSION_INCLUDED #define COMPARISON_EXPRESSION_INCLUDED #include "Expression.h" #include "BinaryOperationExpression.h" /** * Expression implementation of a binary comparison operation. * * Evaluating this expression returns 1 if the comparisson is true * and 0 if it is false. * * @author Jason Rohrer */ class ComparisonExpression : public BinaryOperationExpression { public: static const int GREATER_THAN = 0; static const int LESS_THAN = 1; static const int GREATER_THAN_OR_EQUAL_TO = 2; static const int LESS_THAN_OR_EQUAL_TO = 3; static const int EQUAL_TO = 4; static const int NOT_EQUAL_TO = 5; /** * Constructs a binary comparison operation expression. * * Both arguments are destroyed when the class is destroyed. * * @param inComparison the comparison to make, one of * GREATER_THAN, LESS_THAN, GREATER_THAN_OR_EQUAL_TO, * LESS_THAN_OR_EQUAL_TO, EQUAL_TO, NOT_EQUAL_TO. * @param inArgumentA the first argument. * @param inArgumentB the second argument. */ ComparisonExpression( int inComparison, Expression *inArgumentA, Expression *inArgumentB ); /** * Gets the comparison being made. * * @return one of GREATER_THAN, LESS_THAN, GREATER_THAN_OR_EQUAL_TO, * LESS_THAN_OR_EQUAL_TO, EQUAL_TO, NOT_EQUAL_TO. */ int getComparison(); /** * Sets the comparison to make. * * @param inComparison the comparison to make, one of * GREATER_THAN, LESS_THAN, GREATER_THAN_OR_EQUAL_TO, * LESS_THAN_OR_EQUAL_TO, EQUAL_TO, NOT_EQUAL_TO. */ void setComparison( int inComparison ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; int mComparison; }; // static init long ComparisonExpression::mID = 15; inline ComparisonExpression::ComparisonExpression( int inComparison, Expression *inArgumentA, Expression *inArgumentB ) : BinaryOperationExpression( inArgumentA, inArgumentB ), mComparison( inComparison ) { } inline int ComparisonExpression::getComparison() { return mComparison; } inline void ComparisonExpression::setComparison( int inComparison ) { mComparison = inComparison; } inline double ComparisonExpression::evaluate() { if( mComparison == GREATER_THAN ) { if( mArgumentA->evaluate() > mArgumentB->evaluate() ) { return 1; } else { return 0; } } else if( mComparison == LESS_THAN ) { if( mArgumentA->evaluate() < mArgumentB->evaluate() ) { return 1; } else { return 0; } } else if( mComparison == GREATER_THAN_OR_EQUAL_TO ) { if( mArgumentA->evaluate() >= mArgumentB->evaluate() ) { return 1; } else { return 0; } } else if( mComparison == LESS_THAN_OR_EQUAL_TO ) { if( mArgumentA->evaluate() <= mArgumentB->evaluate() ) { return 1; } else { return 0; } } else if( mComparison == EQUAL_TO ) { if( mArgumentA->evaluate() == mArgumentB->evaluate() ) { return 1; } else { return 0; } } else if( mComparison == NOT_EQUAL_TO ) { if( mArgumentA->evaluate() != mArgumentB->evaluate() ) { return 1; } else { return 0; } } else { // unknown comparison type // default to false return 0; } } inline long ComparisonExpression::getID() { return mID; } inline long ComparisonExpression::staticGetID() { return mID; } inline void ComparisonExpression::print() { printf( "( " ); mArgumentA->print(); if( mComparison == GREATER_THAN ) { printf( " > " ); } else if( mComparison == LESS_THAN ) { printf( " < " ); } else if( mComparison == GREATER_THAN_OR_EQUAL_TO ) { printf( " >= " ); } else if( mComparison == LESS_THAN_OR_EQUAL_TO ) { printf( " <= " ); } else if( mComparison == EQUAL_TO ) { printf( " == " ); } else if( mComparison == NOT_EQUAL_TO ) { printf( " != " ); } else { printf( " UNKNOWN_COMPARISON " ); } mArgumentB->print(); printf( " )" ); } inline Expression *ComparisonExpression::copy() { ComparisonExpression *copy = new ComparisonExpression( mComparison, mArgumentA->copy(), mArgumentB->copy() ); return copy; } #endif between-6+dfsg1.orig/minorGems/math/expression/UnaryOperationExpression.h0000640000175000017500000000551211435543335025552 0ustar pabspabs/* * Modification History * * 2001-February-10 Jason Rohrer * Created. * * 2001-September-4 Jason Rohrer * Changed the destructor to virtual to fix a memory leak. * * 2001-September-9 Jason Rohrer * Changed setArgument to be more intelligent about duplicated calls. * Added an extractArgument() implemenation. */ #ifndef UNARY_OPERATION_EXPRESSION_INCLUDED #define UNARY_OPERATION_EXPRESSION_INCLUDED #include "Expression.h" /** * Abstract base for an unary operation expression object. * * @author Jason Rohrer */ class UnaryOperationExpression : public Expression { public: /** * Constructs a unary operation expression. * * Argument is destroyed when the class is destroyed. * * @param inArgument the argument. Defaults to NULL. */ UnaryOperationExpression( Expression *inArgument = NULL ); virtual ~UnaryOperationExpression(); /** * Sets the argument for the operation. * * @param inArgument the argument. Is destroyed * when the class is destroyed, or by another * call to setArgument. */ void setArgument( Expression *inArgument ); /** * Gets the argument for the operation. * * @return the argument. Is destroyed * when the class is destroyed, or by another * call to setArgumentB. Returns NULL if the * argument was never set. */ Expression *getArgument(); // implements the Expression interface virtual long getNumArguments(); virtual Expression *getArgument( long inArgumentNumber ); virtual void setArgument( long inArgumentNumber, Expression *inArgument ); virtual Expression *extractArgument( long inArgumentNumber ); protected: Expression *mArgument; }; inline UnaryOperationExpression::UnaryOperationExpression( Expression *inArgument ) : mArgument( inArgument ) { } inline UnaryOperationExpression::~UnaryOperationExpression() { if( mArgument != NULL ) { delete mArgument; } } inline void UnaryOperationExpression::setArgument( Expression *inArgument ) { if( mArgument != NULL && inArgument != mArgument ) { delete mArgument; } mArgument = inArgument; } inline Expression *UnaryOperationExpression::getArgument() { return mArgument; } long UnaryOperationExpression::getNumArguments() { return 1; } inline Expression *UnaryOperationExpression::getArgument( long inArgumentNumber ) { if( inArgumentNumber == 0 ) { return getArgument(); } else { return NULL; } } inline void UnaryOperationExpression::setArgument( long inArgumentNumber, Expression *inArgument ) { if( inArgumentNumber == 0 ) { setArgument( inArgument ); return; } else { return; } } inline Expression *UnaryOperationExpression::extractArgument( long inArgumentNumber ) { Expression *returnArg = mArgument; mArgument = NULL; return returnArg; } #endif between-6+dfsg1.orig/minorGems/math/expression/ProductExpression.h0000640000175000017500000000346311435543335024216 0ustar pabspabs/* * Modification History * * 2001-February-11 Jason Rohrer * Created. * * 2001-March-10 Jason Rohrer * Added implementation of copy function. */ #ifndef PRODUCT_EXPRESSION_INCLUDED #define PRODUCT_EXPRESSION_INCLUDED #include "Expression.h" #include "BinaryOperationExpression.h" /** * Expression implementation of a binary product operation. * * @author Jason Rohrer */ class ProductExpression : public BinaryOperationExpression { public: /** * Constructs a binary product operation expression. * * Both arguments are destroyed when the class is destroyed. * * @param inArgumentA the first argument. * @param inArgumentB the second argument. */ ProductExpression( Expression *inArgumentA, Expression *inArgumentB ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; }; // static init long ProductExpression::mID = 5; inline ProductExpression::ProductExpression( Expression *inArgumentA, Expression *inArgumentB ) : BinaryOperationExpression( inArgumentA, inArgumentB ) { } inline double ProductExpression::evaluate() { return mArgumentA->evaluate() * mArgumentB->evaluate(); } inline long ProductExpression::getID() { return mID; } inline long ProductExpression::staticGetID() { return mID; } inline void ProductExpression::print() { printf( "( " ); mArgumentA->print(); printf( " * " ); mArgumentB->print(); printf( " )" ); } inline Expression *ProductExpression::copy() { ProductExpression *copy = new ProductExpression( mArgumentA->copy(), mArgumentB->copy() ); return copy; } #endif between-6+dfsg1.orig/minorGems/math/expression/SqrtExpression.h0000640000175000017500000000334311435543335023524 0ustar pabspabs/* * Modification History * * 2003-April-28 Jason Rohrer * Created. */ #ifndef SQRT_EXPRESSION_INCLUDED #define SQRT_EXPRESSION_INCLUDED #include "Expression.h" #include "UnaryOperationExpression.h" #include /** * Expression implementation of a unary sqrt operation. * * @author Jason Rohrer */ class SqrtExpression : public UnaryOperationExpression { public: /** * Constructs a unary sqrt operation expression. * * Argument is destroyed when the class is destroyed. * * @param inArgument the argument. */ SqrtExpression( Expression *inArgument ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; }; // static init long SqrtExpression::mID = 13; inline SqrtExpression::SqrtExpression( Expression *inArgument ) : UnaryOperationExpression( inArgument ) { } inline double SqrtExpression::evaluate() { return sqrt( mArgument->evaluate() ); } inline long SqrtExpression::getID() { return mID; } inline long SqrtExpression::staticGetID() { return mID; } inline void SqrtExpression::print() { printf( "( sqrt" ); mArgument->print(); printf( " )" ); } inline Expression *SqrtExpression::copy() { SqrtExpression *copy = new SqrtExpression( mArgument->copy() ); return copy; } #endif between-6+dfsg1.orig/minorGems/math/expression/expressionTester.cpp0000640000175000017500000000552611435543335024441 0ustar pabspabs/* * Modification History * * 2001-February-11 Jason Rohrer * Created. * * 2001-February-12 Jason Rohrer * Added code to test serialization. * * 2001-February-24 Jason Rohrer * Fixed incorrect delete usage. * * 2001-April-12 Jason Rohrer * Changed to comply with new FileInput/OutputStream interface * (underlying File must be destroyed explicitly). */ #include "Expression.h" #include "ConstantExpression.h" #include "PowerExpression.h" #include "ProductExpression.h" #include "NegateExpression.h" #include "InvertExpression.h" #include "SinExpression.h" #include "LnExpression.h" #include "SumExpression.h" #include "ExpressionSerializer.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/FileInputStream.h" #include "minorGems/io/file/FileOutputStream.h" // test function for expressions int main() { ProductExpression *expression = new ProductExpression( new PowerExpression( new ConstantExpression( 5 ), new ConstantExpression( 6 ) ), new NegateExpression( new SinExpression( new ConstantExpression( 19 ) ) ) ); InvertExpression *invExpression = new InvertExpression( expression ); SumExpression *sumExpression = new SumExpression( invExpression, new ConstantExpression( 2 ) ); sumExpression->print(); printf( "\n" ); printf( "%f\n", sumExpression->evaluate() ); printf( "Writing to file.\n" ); char **pathSteps = new char*[2]; pathSteps[0] = new char[10]; pathSteps[1] = new char[10]; sprintf( pathSteps[0], "test" ); sprintf( pathSteps[1], "file" ); int *stepLength = new int[2]; stepLength[0] = 4; stepLength[1] = 4; Path *path = new Path( pathSteps, 2, stepLength, false ); File *file = new File( path, "test.out", 8 ); FileOutputStream *outStream = new FileOutputStream( file, false ); char *error = outStream->getLastError(); if( error != NULL ) { printf( "Error: %s\n", error ); delete error; } ExpressionSerializer::serializeExpression( sumExpression, outStream ); delete outStream; delete file; printf( "Reading back in from file.\n" ); pathSteps = new char*[2]; pathSteps[0] = new char[10]; pathSteps[1] = new char[10]; sprintf( pathSteps[0], "test" ); sprintf( pathSteps[1], "file" ); stepLength = new int[2]; stepLength[0] = 4; stepLength[1] = 4; path = new Path( pathSteps, 2, stepLength, false ); file = new File( path, "test.out", 8 ); FileInputStream *inStream = new FileInputStream( file ); error = inStream->getLastError(); if( error != NULL ) { printf( "Error: %s\n", error ); delete error; } Expression *readExpression; ExpressionSerializer::deserializeExpression( &readExpression, inStream ); delete inStream; delete file; readExpression->print(); printf( "\n" ); printf( "%f\n", readExpression->evaluate() ); delete sumExpression; delete readExpression; return 0; } between-6+dfsg1.orig/minorGems/math/expression/ExpressionMutator.h0000640000175000017500000001604111435543335024225 0ustar pabspabs/* * Modification History * * 2001-September-9 Jason Rohrer * Created. * * 2001-September-13 Jason Rohrer * Made an error message more verbose. */ #ifndef EXPRESSION_MUTATOR_INCLUDED #define EXPRESSION_MUTATOR_INCLUDED #include "minorGems/util/random/RandomSource.h" #include "Expression.h" #include "ConstantExpression.h" #include "InvertExpression.h" #include "ProductExpression.h" #include "PowerExpression.h" #include "SumExpression.h" #include "NegateExpression.h" #include "SinExpression.h" #include "FixedConstantExpression.h" #include "MultiConstantArgumentExpression.h" /** * Utility class for mutating expressions. * * Note that the number and position of constant expressions * within the expression will not change during mutation. Thus, * the structure of the expression remains constant while the operations * being performed at each node are mutated. * * @author Jason Rohrer */ class ExpressionMutator { public: /** * Mutates an expression. * * Note that this function's implementation is recursive. * * @param inExpression the expression to mutate. Will be destroyed * by this function (or if not destroyed, then passed back through * the return value). Only the return value, not inExpression, * can be accessed safely after this function returns. * @param inMutationProb the probability of mutations at each * node in inExpression. * @param inMaxMutation the fraction of a fixed constant's value * by which it can be mutated. For example, if a fixed constant * has the value 100, and inMaxMutation is 0.5, then the mutated * constant will be a random value in the range [50, 150]. * @param inRandSource the source of random numbers to use. * Must be destroyed by caller. * * @return a new expression that is a mutated version of inExpression. * (Note that the returned expression may be inExpression). */ static Expression *mutateExpression( Expression *inExpression, double inMutationProb, double inMaxMutation, RandomSource *inRandSource ); }; inline Expression *ExpressionMutator::mutateExpression( Expression *inExpression, double inMutationProb, double inMaxMutation, RandomSource *inRandSource ) { long expressionID = inExpression->getID(); // first, deal with constant case if( expressionID == ConstantExpression::staticGetID() ) { // mutate the constant's value ConstantExpression *c = (ConstantExpression *)inExpression; double value = c->getValue(); double maxMutationAmount = inMaxMutation * value; // a value in [-1, 1] double mutator = ( inRandSource->getRandomDouble() * 2.0 ) - 1.0; value = value + mutator * maxMutationAmount; c->setValue( value ); return c; } else if( expressionID == FixedConstantExpression::staticGetID() ) { // mutate the fixed constant's value FixedConstantExpression *c = (FixedConstantExpression *)inExpression; double value = c->getValue(); double maxMutationAmount = inMaxMutation * value; // a value in [-1, 1] double mutator = ( inRandSource->getRandomDouble() * 2.0 ) - 1.0; value = value + mutator * maxMutationAmount; delete c; return new FixedConstantExpression( value ); } // next deal with the multi-argument case else if( expressionID == MultiConstantArgumentExpression::staticGetID() ) { MultiConstantArgumentExpression *m = (MultiConstantArgumentExpression*)inExpression; Expression *wrappedExpression = m->extractWrappedExpression(); wrappedExpression = mutateExpression( wrappedExpression, inMutationProb, inMaxMutation, inRandSource ); m->setWrappedExpression( wrappedExpression ); return m; } else { // the general expression case Expression *newExpression = inExpression; if( inRandSource->getRandomDouble() <= inMutationProb ) { // we need to mutate this node long newID; if( expressionID == InvertExpression::staticGetID() || expressionID == NegateExpression::staticGetID() || expressionID == SinExpression::staticGetID() ) { // a unary expression // pick another expression type at random newID = expressionID; while( newID == expressionID ) { int randValue = inRandSource->getRandomBoundedInt( 0, 2 ); switch( randValue ) { case 0: newID = InvertExpression::staticGetID(); break; case 1: newID = NegateExpression::staticGetID(); break; case 2: newID = SinExpression::staticGetID(); break; default: // we should never hit this // note that this newID will cause a printed // error below newID = -1; break; } } } else { // a binary expression // pick another expression type at random newID = expressionID; while( newID == expressionID ) { int randValue = inRandSource->getRandomBoundedInt( 0, 2 ); switch( randValue ) { case 0: newID = PowerExpression::staticGetID(); break; case 1: newID = ProductExpression::staticGetID(); break; case 2: newID = SumExpression::staticGetID(); break; default: // we should never hit this // note that this newID will cause a printed // error below newID = -1; break; } } } // now build an expression based on newID if( newID == InvertExpression::staticGetID() ) { newExpression = new InvertExpression( NULL ); } else if( newID == NegateExpression::staticGetID() ) { newExpression = new NegateExpression( NULL ); } else if( newID == PowerExpression::staticGetID() ) { newExpression = new PowerExpression( NULL, NULL ); } else if( newID == ProductExpression::staticGetID() ) { newExpression = new ProductExpression( NULL, NULL ); } else if( newID == SinExpression::staticGetID() ) { newExpression = new SinExpression( NULL ); } else if( newID == SumExpression::staticGetID() ) { newExpression = new SumExpression( NULL, NULL ); } else { printf( "Error in ExpressionMutator: ID does not " ); printf( "match a known expression type: %d\n", newID ); } // at this point, we have constructed a new expression node // with the same number of arguments as the old node // we need to fill in the arguments from inExpression for( int i=0; igetNumArguments(); i++ ) { // use extractArgument so that the argument // won't be destroyed when inExpression is destroyed Expression *argument = inExpression->extractArgument( i ); newExpression->setArgument( i, argument ); } // destroy the old node delete inExpression; } // mutate the sub nodes for( int i=0; igetNumArguments(); i++ ) { Expression *argument = newExpression->extractArgument( i ); // mutate the argument argument = mutateExpression( argument, inMutationProb, inMaxMutation, inRandSource ); newExpression->setArgument( i, argument ); } return newExpression; } } #endif between-6+dfsg1.orig/minorGems/math/expression/PowerExpression.h0000640000175000017500000000356711435543335023677 0ustar pabspabs/* * Modification History * * 2001-February-11 Jason Rohrer * Created. * * 2001-March-10 Jason Rohrer * Added implementation of copy function. */ #ifndef POWER_EXPRESSION_INCLUDED #define POWER_EXPRESSION_INCLUDED #include "Expression.h" #include "BinaryOperationExpression.h" #include /** * Expression implementation of a binary power operation. * Raises the first argument to the power of the second, * as in argA^argB. * * @author Jason Rohrer */ class PowerExpression : public BinaryOperationExpression { public: /** * Constructs a binary power operation expression. * * Both arguments are destroyed when the class is destroyed. * * @param inArgumentA the first argument. * @param inArgumentB the second argument. */ PowerExpression( Expression *inArgumentA, Expression *inArgumentB ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; }; // static init long PowerExpression::mID = 4; inline PowerExpression::PowerExpression( Expression *inArgumentA, Expression *inArgumentB ) : BinaryOperationExpression( inArgumentA, inArgumentB ) { } inline double PowerExpression::evaluate() { return pow( mArgumentA->evaluate(), mArgumentB->evaluate() ); } inline long PowerExpression::getID() { return mID; } inline long PowerExpression::staticGetID() { return mID; } inline void PowerExpression::print() { printf( "( " ); mArgumentA->print(); printf( " ^ " ); mArgumentB->print(); printf( " )" ); } inline Expression *PowerExpression::copy() { PowerExpression *copy = new PowerExpression( mArgumentA->copy(), mArgumentB->copy() ); return copy; } #endif between-6+dfsg1.orig/minorGems/math/expression/TanExpression.h0000640000175000017500000000332111435543335023311 0ustar pabspabs/* * Modification History * * 2003-April-28 Jason Rohrer * Created. */ #ifndef TAN_EXPRESSION_INCLUDED #define TAN_EXPRESSION_INCLUDED #include "Expression.h" #include "UnaryOperationExpression.h" #include /** * Expression implementation of a unary tan operation. * * @author Jason Rohrer */ class TanExpression : public UnaryOperationExpression { public: /** * Constructs a unary tan operation expression. * * Argument is destroyed when the class is destroyed. * * @param inArgument the argument. */ TanExpression( Expression *inArgument ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; }; // static init long TanExpression::mID = 12; inline TanExpression::TanExpression( Expression *inArgument ) : UnaryOperationExpression( inArgument ) { } inline double TanExpression::evaluate() { return tan( mArgument->evaluate() ); } inline long TanExpression::getID() { return mID; } inline long TanExpression::staticGetID() { return mID; } inline void TanExpression::print() { printf( "( tan" ); mArgument->print(); printf( " )" ); } inline Expression *TanExpression::copy() { TanExpression *copy = new TanExpression( mArgument->copy() ); return copy; } #endif between-6+dfsg1.orig/minorGems/math/expression/BinaryOperationExpression.h0000640000175000017500000001045111435543335025676 0ustar pabspabs/* * Modification History * * 2001-February-10 Jason Rohrer * Created. * * 2001-September-4 Jason Rohrer * Changed the destructor to virtual to fix a memory leak. * * 2001-September-9 Jason Rohrer * Changed setArgument to be more intelligent about duplicated calls. * Added an extractArgument() implemenation. */ #ifndef BINARY_OPERATION_EXPRESSION_INCLUDED #define BINARY_OPERATION_EXPRESSION_INCLUDED #include "Expression.h" /** * Abstract base for an binary operation expression object. * * @author Jason Rohrer */ class BinaryOperationExpression : public Expression { public: /** * Constructs a binary operation expression. * * Both arguments are destroyed when the class is destroyed. * * @param inArgumentA the first argument. Defaults to NULL. * @param inArgumentA the first argument. Defaults to NULL. */ BinaryOperationExpression( Expression *inArgumentA = NULL, Expression *inArgumentB = NULL ); virtual ~BinaryOperationExpression(); /** * Sets the first argument for the operation. * * @param inArgument the first argument. Is destroyed * when the class is destroyed, or by another * call to setArgumentA. */ void setArgumentA( Expression *inArgument ); /** * Sets the second argument for the operation. * * @param inArgument the second argument. Is destroyed * when the class is destroyed, or by another * call to setArgumentB. */ void setArgumentB( Expression *inArgument ); /** * Gets the first argument for the operation. * * @return the first argument. Is destroyed * when the class is destroyed, or by another * call to setArgumentB. Returns NULL if the * argument was never set. */ Expression *getArgumentA(); /** * Gets the second argument for the operation. * * @return the second argument. Is destroyed * when the class is destroyed, or by another * call to setArgumentB. Returns NULL if the * argument was never set. */ Expression *getArgumentB(); // implements the Expression interface virtual long getNumArguments(); virtual Expression *getArgument( long inArgumentNumber ); virtual void setArgument( long inArgumentNumber, Expression *inArgument ); virtual Expression *extractArgument( long inArgumentNumber ); protected: Expression *mArgumentA; Expression *mArgumentB; }; inline BinaryOperationExpression::BinaryOperationExpression( Expression *inArgumentA, Expression *inArgumentB ) : mArgumentA( inArgumentA ), mArgumentB( inArgumentB ) { } inline BinaryOperationExpression::~BinaryOperationExpression() { if( mArgumentA != NULL ) { delete mArgumentA; } if( mArgumentB != NULL ) { delete mArgumentB; } } inline void BinaryOperationExpression::setArgumentA( Expression *inArgument ) { if( mArgumentA != NULL && inArgument != mArgumentA ) { delete mArgumentA; } mArgumentA = inArgument; } inline void BinaryOperationExpression::setArgumentB( Expression *inArgument ) { if( mArgumentB != NULL && inArgument != mArgumentB ) { delete mArgumentB; } mArgumentB = inArgument; } inline Expression *BinaryOperationExpression::getArgumentA() { return mArgumentA; } inline Expression *BinaryOperationExpression::getArgumentB() { return mArgumentB; } inline long BinaryOperationExpression::getNumArguments() { return 2; } inline Expression *BinaryOperationExpression::getArgument( long inArgumentNumber ) { switch( inArgumentNumber ) { case 0: return getArgumentA(); break; case 1: return getArgumentB(); break; default: return NULL; break; } } inline void BinaryOperationExpression::setArgument( long inArgumentNumber, Expression *inArgument ) { switch( inArgumentNumber ) { case 0: setArgumentA( inArgument ); return; break; case 1: setArgumentB( inArgument ); return; break; default: return; break; } } inline Expression *BinaryOperationExpression::extractArgument( long inArgumentNumber ) { Expression *returnArg; switch( inArgumentNumber ) { case 0: returnArg = mArgumentA; mArgumentA = NULL; return returnArg; break; case 1: returnArg = mArgumentB; mArgumentB = NULL; return returnArg; break; default: return NULL; break; } } #endif between-6+dfsg1.orig/minorGems/math/expression/MultiConstantArgumentExpression.h0000640000175000017500000002001211435543335027072 0ustar pabspabs/* * Modification History * * 2001-August-30 Jason Rohrer * Created. * * 2001-August-31 Jason Rohrer * Added public access to the wrapped expression. * Fixed a comment and some bugs. * Fixed a memory leak. * * 2001-September-9 Jason Rohrer * Added public function for setting the wrapped expression after * construction. * Added an extractArgument() implemenation. * Added an extractWrappedExpression() function to work * around some destruction issues. */ #ifndef MULTI_CONSTANT_ARGUMENT_EXPRESSION_INCLUDED #define MULTI_CONSTANT_ARGUMENT_EXPRESSION_INCLUDED #include "Expression.h" #include "ConstantExpression.h" #include "minorGems/util/SimpleVector.h" /** * An expression implementation that treats the constants * in another expression as assignable arguments. * * Most common usage pattern: * Set up an Expression containing one constant for each * assignable argument and pass this expression into * the constructor. * * Notes: * * getArugment() returns the actual constant expression * contained in the wrapped expression. It therefore * should not be destroyed by the caller. * * setArgument() evaluates the passed-in expression * and then sets the value of the constant expression to the * value produced by the evaluation. * The passed-in expression must be destroyed by the caller, * and it can be destroyed as soon as setArgument() returns. * * @author Jason Rohrer */ class MultiConstantArgumentExpression : public Expression { public: /** * Constructs a new MultiArgumentExpression. * * @param inExpression the expression to use as the * body of this new expression, where each constant in * inExpression will be used as an argument to the * new expression. Will be destroyed when this class * is destroyed. */ MultiConstantArgumentExpression( Expression *inExpression ); ~MultiConstantArgumentExpression(); /** * Sets the expression wrapped by this mult-argument expression. * * Note that calling this function destroys the currently wrapped * expression. * * @param inExpression the expression to use as the * body of this new expression, where each constant in * inExpression will be used as an argument to the * new expression. Will be destroyed when this class * is destroyed. */ void setWrappedExpression( Expression *inExpression ); /** * Gets the expression wrapped by this mult-argument expression. * * @return the expression wrapped by this expression. * Will be destroyed when this class is destroyed. */ Expression *getWrappedExpression(); /** * Gets the expression wrapped by this mult-argument expression, * and sets the internal expression to NULL (thus, the returned * argument will not be destroyed when this class is destroyed. * * @return the expression wrapped by this expression. Must * be destroyed by caller. */ Expression *extractWrappedExpression(); // these implement the Expression interface virtual double evaluate(); virtual long getID(); virtual long getNumArguments(); virtual Expression *getArgument( long inArgumentNumber ); virtual void setArgument( long inArgumentNumber, Expression *inArgument ); // note that extractArgument() always returns NULL for this class virtual Expression *extractArgument( long inArgumentNumber ); virtual void print(); virtual Expression *copy(); /** * A static version of getID(). */ static long staticGetID(); protected: Expression *mExpression; static long mID; long mNumConstants; ConstantExpression **mConstants; /** * Finds the constants in an expression in a consistent way * (using depth-first, left-first search). * * @param inExpression the expression to search for constants in. * @param outExpressions a pointer where the array of found * expressions will be returned. * * @return the number of constants found. */ long findConstants( Expression *inExpression, ConstantExpression ***outExpressions ); /** * Recursive proceedure used by findConstants() * * @param inExpression the (sub)expression to find constants in. * @param inConstantVector the vector to add found constants to. */ void findConstantsRecursive( Expression *inExpression, SimpleVector *inConstantVector ); }; // static init long MultiConstantArgumentExpression::mID = 8; inline MultiConstantArgumentExpression:: MultiConstantArgumentExpression( Expression *inExpression ) : mExpression( NULL ), mConstants( NULL ) { setWrappedExpression( inExpression ); } inline MultiConstantArgumentExpression:: ~MultiConstantArgumentExpression() { delete [] mConstants; delete mExpression; } inline void MultiConstantArgumentExpression:: setWrappedExpression( Expression *inExpression ) { if( mExpression != NULL && mExpression != inExpression ) { delete mExpression; } mExpression = inExpression; if( mConstants != NULL ) { delete [] mConstants; } mNumConstants = findConstants( inExpression, &mConstants ); } inline Expression *MultiConstantArgumentExpression:: getWrappedExpression() { return mExpression; } inline Expression *MultiConstantArgumentExpression:: extractWrappedExpression() { Expression *wrappedExpression = mExpression; mExpression = NULL; return wrappedExpression; } inline double MultiConstantArgumentExpression::evaluate() { return mExpression->evaluate(); } inline long MultiConstantArgumentExpression::getID() { return mID; } inline long MultiConstantArgumentExpression::staticGetID() { return mID; } inline long MultiConstantArgumentExpression::getNumArguments() { return mNumConstants; } inline Expression *MultiConstantArgumentExpression::getArgument( long inArgumentNumber ) { if( inArgumentNumber >= 0 && inArgumentNumber < mNumConstants ) { return mConstants[inArgumentNumber]; } else { return NULL; } } inline void MultiConstantArgumentExpression::setArgument( long inArgumentNumber, Expression *inArgument ) { Expression *expressionToSet = getArgument( inArgumentNumber ); if( expressionToSet != NULL ) { ConstantExpression *constantExpression = (ConstantExpression*)expressionToSet; // set the constant to the evaluation of inArgument constantExpression->setValue( inArgument->evaluate() ); } else { printf( "MultiConstantArgumentExpression: setting an out of range " ); printf( "argument number, %ld\n", inArgumentNumber ); } } inline Expression *MultiConstantArgumentExpression::extractArgument( long inArgumentNumber ) { return NULL; } inline void MultiConstantArgumentExpression::print() { mExpression->print(); } inline Expression *MultiConstantArgumentExpression::copy() { return new MultiConstantArgumentExpression( mExpression->copy() ); } inline long MultiConstantArgumentExpression::findConstants( Expression *inExpression, ConstantExpression ***outExpressions ) { SimpleVector *constantVector = new SimpleVector(); findConstantsRecursive( inExpression, constantVector ); long numConstants = constantVector->size(); ConstantExpression **returnArray = new ConstantExpression*[ numConstants ]; for( int i=0; igetElement(i) ); } delete constantVector; // set passed-in pointer to our array *outExpressions = returnArray; return numConstants; } inline void MultiConstantArgumentExpression::findConstantsRecursive( Expression *inExpression, SimpleVector *inConstantVector ) { if( inExpression->getID() == ConstantExpression::staticGetID() ) { // the passed-in expression is a constant inConstantVector->push_back( (ConstantExpression *)inExpression ); return; } else { // call recursively on each argument for( int i=0; igetNumArguments(); i++ ) { Expression *argument = inExpression->getArgument( i ); findConstantsRecursive( argument, inConstantVector ); } return; } } #endif between-6+dfsg1.orig/minorGems/math/expression/LnExpression.h0000640000175000017500000000331611435543335023144 0ustar pabspabs/* * Modification History * * 2003-April-28 Jason Rohrer * Created. */ #ifndef LN_EXPRESSION_INCLUDED #define LN_EXPRESSION_INCLUDED #include "Expression.h" #include "UnaryOperationExpression.h" #include /** * Expression implementation of a unary ln (natural log) operation. * * @author Jason Rohrer */ class LnExpression : public UnaryOperationExpression { public: /** * Constructs a unary ln operation expression. * * Argument is destroyed when the class is destroyed. * * @param inArgument the argument. */ LnExpression( Expression *inArgument ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; }; // static init long LnExpression::mID = 10; inline LnExpression::LnExpression( Expression *inArgument ) : UnaryOperationExpression( inArgument ) { } inline double LnExpression::evaluate() { return log( mArgument->evaluate() ); } inline long LnExpression::getID() { return mID; } inline long LnExpression::staticGetID() { return mID; } inline void LnExpression::print() { printf( "( ln" ); mArgument->print(); printf( " )" ); } inline Expression *LnExpression::copy() { LnExpression *copy = new LnExpression( mArgument->copy() ); return copy; } #endif between-6+dfsg1.orig/minorGems/math/expression/SinExpression.h0000640000175000017500000000305311435543335023322 0ustar pabspabs/* * Modification History * * 2001-February-11 Jason Rohrer * Created. * * 2001-March-10 Jason Rohrer * Added implementation of copy function. */ #ifndef SIN_EXPRESSION_INCLUDED #define SIN_EXPRESSION_INCLUDED #include "Expression.h" #include "UnaryOperationExpression.h" #include /** * Expression implementation of a unary sin operation. * * @author Jason Rohrer */ class SinExpression : public UnaryOperationExpression { public: /** * Constructs a unary sin operation expression. * * Argument is destroyed when the class is destroyed. * * @param inArgument the argument. */ SinExpression( Expression *inArgument ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; }; // static init long SinExpression::mID = 6; inline SinExpression::SinExpression( Expression *inArgument ) : UnaryOperationExpression( inArgument ) { } inline double SinExpression::evaluate() { return sin( mArgument->evaluate() ); } inline long SinExpression::getID() { return mID; } inline long SinExpression::staticGetID() { return mID; } inline void SinExpression::print() { printf( "( sin" ); mArgument->print(); printf( " )" ); } inline Expression *SinExpression::copy() { SinExpression *copy = new SinExpression( mArgument->copy() ); return copy; } #endif between-6+dfsg1.orig/minorGems/math/expression/Expression.h0000640000175000017500000000717411435543335022660 0ustar pabspabs/* * Modification History * * 2001-February-10 Jason Rohrer * Created. * * 2001-March-7 Jason Rohrer * Added a copy() function interface. * * 2001-September-4 Jason Rohrer * Added a virtual destructor to fix a major memory leak. * * 2001-September-9 Jason Rohrer * Added an extractArgument() function to work around some * object destruction issues. * * 2003-May-9 Jason Rohrer * Added support for replacing a variable. */ #ifndef EXPRESSION_INCLUDED #define EXPRESSION_INCLUDED #include #include "Variable.h" /** * Interface for an expression object. * * @author Jason Rohrer */ class Expression { public: virtual ~Expression(); /** * Evaluates this expression. * * @return the value of this expression. */ virtual double evaluate() = 0; /** * Gets the unique ID of this expression subtype. * * @return the ID of this subtype. */ virtual long getID() = 0; /** * Gets the number of arguments taken by this expression subtype. * * @return the number of arguments for this subtype. */ virtual long getNumArguments() = 0; /** * Gets a specified argument for this expression. * * @param inArgumentNumber the index of this argument. * * @return the specified argument. Will be destroyed * when this class is destroyed. Returns NULL if * the argument has not been set. */ virtual Expression *getArgument( long inArgumentNumber ) = 0; /** * Sets a specified argument for this expression. * * @param inArgumentNumber the index of this argument. * @param inArgument the specified argument. Will be destroyed * when this class is destroyed, or by another call to * setArgument. */ virtual void setArgument( long inArgumentNumber, Expression *inArgument ) = 0; /** * Extracts an argument from this expression. * * This is similar to getArgument(), except that internally * this expression's argument is set to NULL. In other words, * this allows you to setArgument( NULL ) without destroying * the argument. * * @param inArgumentNumber the argument to get. Must be destroyed * by caller. Returns NULL if the argument has not been set. */ virtual Expression *extractArgument( long inArgumentNumber ) = 0; /** * Prints this expression to standard out. */ virtual void print() = 0; /** * Makes a copy of this expression recursively. * * @return a copy of this expression. */ virtual Expression *copy() = 0; /** * Recursively replace a variable in this expression. * * Default implementation calls replacement recursively on each * argument. Expressions that actually deal with variables * should override this implementation. * * @param inTarget the target to replace. * Must be destroyed by caller. * @param inReplacement the variable to replace the target with. * Must be destroyed by caller after this expression is destroyed. */ virtual void replaceVariable( Variable *inTarget, Variable *inReplacement ); }; inline Expression::~Expression() { // do nothing } inline void Expression::replaceVariable( Variable *inTarget, Variable *inReplacement ) { // call recursively on each of our arguments int numArgs = getNumArguments(); for( int i=0; ireplaceVariable( inTarget, inReplacement ); } } #endif between-6+dfsg1.orig/minorGems/math/expression/RandomVariable.h0000640000175000017500000000265311435543335023404 0ustar pabspabs/* * Modification History * * 2003-May-4 Jason Rohrer * Created. */ #ifndef RANDOM_VARIABLE_INCLUDED #define RANDOM_VARIABLE_INCLUDED #include "minorGems/util/stringUtils.h" #include "minorGems/util/random/RandomSource.h" /** * Wrapper for a random-valued variable. * * @author Jason Rohrer */ class RandomVariable : public Variable{ public: /** * Constructs a variable * * @param inName the name of the variable. * Must be destroyed by caller if non-const. * @param inRandSource the source for random numbers. * Must be destroyed by caller after this class is destroyed. */ RandomVariable( char *inName, RandomSource *inRandSource ); virtual ~RandomVariable(); // overrides Variable functions virtual double getValue(); virtual void setValue( double inValue ); protected: RandomSource *mRandSource; }; inline RandomVariable::RandomVariable( char *inName, RandomSource *inRandSource ) : Variable( inName, 0 ), mRandSource( inRandSource ) { } inline RandomVariable::~RandomVariable() { } inline double RandomVariable::getValue() { return mRandSource->getRandomDouble(); } inline void RandomVariable::setValue( double inValue ) { // do nothing } #endif between-6+dfsg1.orig/minorGems/math/expression/RandomExpressionFactory.h0000640000175000017500000001005711435543335025343 0ustar pabspabs/* * Modification History * * 2001-August-30 Jason Rohrer * Created. * * 2001-August-31 Jason Rohrer * Finished implementation. * Fixed a compile bug. * * 2001-September-4 Jason Rohrer * Added support for FixedConstantExpressions. */ #ifndef RANDOM_EXPRESSION_FACTORY_INCLUDED #define RANDOM_EXPRESSION_FACTORY_INCLUDED #include "Expression.h" #include "ConstantExpression.h" #include "FixedConstantExpression.h" #include "InvertExpression.h" #include "ProductExpression.h" #include "PowerExpression.h" #include "SumExpression.h" #include "NegateExpression.h" #include "SinExpression.h" #include "minorGems/util/random/RandomSource.h" /** * Utility class for constructing random expressions. * * @author Jason Rohrer */ class RandomExpressionFactory { public: /** * Constructs a random expression factory. * * @param inRandSource the source for random numbers * to use while constructing expressions. * Must be destroyed by caller after this class is destroyed. */ RandomExpressionFactory( RandomSource *inRandSource ); /** * Recursively constructs a random expression with all parameters * filled. * * @param inProbOfStopping the probability of stopping at each * branch of the expression. Upon stopping on a certain branch * of the recursion, it simply returns a constant expression. * @param inProbOfFixedConstant the probability of a fixed * constant expression being inserted upon stopping (as opposed * to a (mutable) constant expression). * @param inMaxDepth if this is reached, the recursion * stops regardless of inProbOfStopping. * @param inConstantMax the maximum value for a constant expression. * * @return the constructed expression. */ Expression *constructRandomExpression( double inProbOfStopping, double inProbOfFixedConstant, int inMaxDepth, double inConstantMax ); protected: RandomSource *mRandSource; }; inline RandomExpressionFactory::RandomExpressionFactory( RandomSource *inRandSource ) : mRandSource( inRandSource ) { } inline Expression *RandomExpressionFactory::constructRandomExpression( double inProbOfStopping, double inProbOfFixedConstant, int inMaxDepth, double inConstantMax ) { // fill in constant expressions only at the leaves if( inMaxDepth == 0 || mRandSource->getRandomDouble() <= inProbOfStopping ) { // stop if( mRandSource->getRandomDouble() <= inProbOfFixedConstant ) { return new FixedConstantExpression( inConstantMax * ( mRandSource->getRandomDouble() ) ); } else { return new ConstantExpression( inConstantMax * ( mRandSource->getRandomDouble() ) ); } } else { // keep filling in non constant expressions randomly // FILL IN HERE // we have 6 expression types int randVal = mRandSource->getRandomBoundedInt( 0, 3 ); Expression *outExpression; // pick an expression type switch( randVal ) { case 0: outExpression = new NegateExpression( NULL ); break; case 1: outExpression = new ProductExpression( NULL, NULL ); break; case 2: outExpression = new SinExpression( NULL ); break; case 3: outExpression = new SumExpression( NULL, NULL ); break; default: // should never happen, but... printf( "RandomExpressionFactory: " ); printf( "Error while generating random expression\n" ); // default to a constant expression of 0 outExpression = new ConstantExpression( 0 ); break; } // now recursively fill in the arguments in succession for( int i=0; igetNumArguments(); i++ ) { // create a random expression as the argument // note that we decrement inMaxDepth here Expression *argument = constructRandomExpression( inProbOfStopping, inProbOfFixedConstant, inMaxDepth - 1, inConstantMax ); // set the argument into our expression outExpression->setArgument( i, argument ); } // now expression is complete. return outExpression; } // end of non-constant else case } // end of constructRandomExpression() #endif between-6+dfsg1.orig/minorGems/math/expression/NegateExpression.h0000640000175000017500000000306611435543335024000 0ustar pabspabs/* * Modification History * * 2001-February-11 Jason Rohrer * Created. * * 2001-March-10 Jason Rohrer * Added implementation of copy function. */ #ifndef NEGATE_EXPRESSION_INCLUDED #define NEGATE_EXPRESSION_INCLUDED #include "Expression.h" #include "UnaryOperationExpression.h" /** * Expression implementation of a unary negate operation. * * @author Jason Rohrer */ class NegateExpression : public UnaryOperationExpression { public: /** * Constructs a unary negate operation expression. * * Argument is destroyed when the class is destroyed. * * @param inArgument the argument. */ NegateExpression( Expression *inArgument ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; }; // static init long NegateExpression::mID = 3; inline NegateExpression::NegateExpression( Expression *inArgument ) : UnaryOperationExpression( inArgument ) { } inline double NegateExpression::evaluate() { return -( mArgument->evaluate() ); } inline long NegateExpression::getID() { return mID; } inline long NegateExpression::staticGetID() { return mID; } inline void NegateExpression::print() { printf( "( -" ); mArgument->print(); printf( " )" ); } inline Expression *NegateExpression::copy() { NegateExpression *copy = new NegateExpression( mArgument->copy() ); return copy; } #endif between-6+dfsg1.orig/minorGems/math/expression/FixedConstantExpression.h0000640000175000017500000000444611435543335025351 0ustar pabspabs/* * Modification History * * 2001-September-4 Jason Rohrer * Created. * * 2001-September-9 Jason Rohrer * Added an extractArgument() implemenation. */ #ifndef FIXED_CONSTANT_EXPRESSION_INCLUDED #define FIXED_CONSTANT_EXPRESSION_INCLUDED #include "Expression.h" /** * Expression implementation of a fixed constant. * * @author Jason Rohrer */ class FixedConstantExpression : public Expression { public: /** * Constructs a FixedConstant expression. * * @param inValue the constant value. */ FixedConstantExpression( double inValue ); /** * Gets the constant value. * * @return the constant value. */ double getValue(); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getNumArguments(); virtual long getID(); virtual Expression *copy(); virtual Expression *getArgument( long inArgumentNumber ); virtual void setArgument( long inArgumentNumber, Expression *inArgument ); virtual Expression *extractArgument( long inArgumentNumber ); virtual void print(); protected: double mValue; static long mID; }; // static init long FixedConstantExpression::mID = 9; inline FixedConstantExpression::FixedConstantExpression( double inValue ) : mValue( inValue ) { } inline double FixedConstantExpression::getValue() { return mValue; } inline double FixedConstantExpression::evaluate() { return mValue; } long FixedConstantExpression::getNumArguments() { return 0; } inline long FixedConstantExpression::getID() { return mID; } inline Expression *FixedConstantExpression::getArgument( long inArgumentNumber ) { return NULL; } inline void FixedConstantExpression::setArgument( long inArgumentNumber, Expression *inArgument ) { // do nothing return; } inline Expression *FixedConstantExpression::extractArgument( long inArgumentNumber ) { return NULL; } inline Expression *FixedConstantExpression::copy() { FixedConstantExpression *copy = new FixedConstantExpression( mValue ); return copy; } inline long FixedConstantExpression::staticGetID() { return mID; } inline void FixedConstantExpression::print() { printf( "( %f )", mValue ); } #endif between-6+dfsg1.orig/minorGems/math/expression/CosExpression.h0000640000175000017500000000332111435543335023313 0ustar pabspabs/* * Modification History * * 2003-April-28 Jason Rohrer * Created. */ #ifndef COS_EXPRESSION_INCLUDED #define COS_EXPRESSION_INCLUDED #include "Expression.h" #include "UnaryOperationExpression.h" #include /** * Expression implementation of a unary cos operation. * * @author Jason Rohrer */ class CosExpression : public UnaryOperationExpression { public: /** * Constructs a unary cos operation expression. * * Argument is destroyed when the class is destroyed. * * @param inArgument the argument. */ CosExpression( Expression *inArgument ); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); protected: static long mID; }; // static init long CosExpression::mID = 11; inline CosExpression::CosExpression( Expression *inArgument ) : UnaryOperationExpression( inArgument ) { } inline double CosExpression::evaluate() { return cos( mArgument->evaluate() ); } inline long CosExpression::getID() { return mID; } inline long CosExpression::staticGetID() { return mID; } inline void CosExpression::print() { printf( "( cos" ); mArgument->print(); printf( " )" ); } inline Expression *CosExpression::copy() { CosExpression *copy = new CosExpression( mArgument->copy() ); return copy; } #endif between-6+dfsg1.orig/minorGems/math/expression/VariableExpression.h0000640000175000017500000000633311435543335024322 0ustar pabspabs/* * Modification History * * 2003-April-29 Jason Rohrer * Created. * * 2003-May-9 Jason Rohrer * Added support for replacing a variable. */ #ifndef VARIABLE_EXPRESSION_INCLUDED #define VARIABLE_EXPRESSION_INCLUDED #include "Expression.h" #include "Variable.h" /** * Expression that contains a single variable. * * @author Jason Rohrer */ class VariableExpression : public Expression { public: /** * Constructs a variable expression. * * @param inVariable the variable. * Must be destroyed by caller after this class is destroyed. */ VariableExpression( Variable *inVariable ); /** * Gets this expression's variable. * * @return the variable. * Must not be destroyed by caller. */ Variable *getVariable(); /** * A static version of getID(). */ static long staticGetID(); // implements the Expression interface virtual double evaluate(); virtual long getID(); virtual void print(); virtual Expression *copy(); virtual long getNumArguments(); virtual Expression *getArgument( long inArgumentNumber ); virtual void setArgument( long inArgumentNumber, Expression *inArgument ); virtual Expression *extractArgument( long inArgumentNumber ); // overrides the default implementation virtual void replaceVariable( Variable *inTarget, Variable *inReplacement ); protected: static long mID; Variable *mVariable; }; // static init long VariableExpression::mID = 14; inline VariableExpression::VariableExpression( Variable *inVariable ) : mVariable( inVariable ) { } inline Variable *VariableExpression::getVariable() { return mVariable; } inline double VariableExpression::evaluate() { return mVariable->getValue(); } inline long VariableExpression::getID() { return mID; } inline long VariableExpression::staticGetID() { return mID; } inline void VariableExpression::print() { char *varName = mVariable->getName(); printf( " %s ", varName ); delete [] varName; } inline Expression *VariableExpression::copy() { // don't copy our variable VariableExpression *copy = new VariableExpression( mVariable ); return copy; } long VariableExpression::getNumArguments() { return 0; } inline Expression *VariableExpression::getArgument( long inArgumentNumber ) { return NULL; } inline void VariableExpression::setArgument( long inArgumentNumber, Expression *inArgument ) { // do nothing return; } inline Expression *VariableExpression::extractArgument( long inArgumentNumber ) { return NULL; } inline void VariableExpression::replaceVariable( Variable *inTarget, Variable *inReplacement ) { if( mVariable == inTarget ) { mVariable = inReplacement; } } #endif between-6+dfsg1.orig/minorGems/math/expression/ExpressionSerializer.h0000640000175000017500000001374711435543335024715 0ustar pabspabs/* * Modification History * * 2001-February-11 Jason Rohrer * Created. * * 2001-March-7 Jason Rohrer * Removed and extra if statement from the deserialization function. * * 2001-August-31 Jason Rohrer * Added support for MultiConstantArgumentExpressions. * * 2001-September-4 Jason Rohrer * Added support for FixedConstantExpressions. * * 2001-October-9 Jason Rohrer * Fixed a bug in deserializing MultiConstantArgumentExpressions. */ #ifndef EXPRESSION_SERIALIZER_INCLUDED #define EXPRESSION_SERIALIZER_INCLUDED #include "Expression.h" #include "UnaryOperationExpression.h" #include "BinaryOperationExpression.h" #include "ConstantExpression.h" #include "InvertExpression.h" #include "ProductExpression.h" #include "PowerExpression.h" #include "SumExpression.h" #include "NegateExpression.h" #include "SinExpression.h" #include "FixedConstantExpression.h" #include "MultiConstantArgumentExpression.h" #include "minorGems/io/OutputStream.h" #include "minorGems/io/InputStream.h" #include "minorGems/io/TypeIO.h" /** * Utility class for serializing expressions * * @author Jason Rohrer */ class ExpressionSerializer { public: /** * Serializes an expression onto a stream. * * @param inExpression the expression to serialize. * @param inOutputStream the stream to write to. * * @return the number of bytes written. */ static long serializeExpression( Expression *inExpression, OutputStream *inOutputStream ); /** * Deserializes an expression from a stream. * * @param outExpression a pointer to where the expression * pointer will be returned. A new expression is created, * and it must be destroyed by the caller. * @param inInputStream the stream to read from. * * @return the number of bytes read. */ static long deserializeExpression( Expression **outExpression, InputStream *inInputStream ); }; // these can both be implemented recursively... exciting! inline long ExpressionSerializer::serializeExpression( Expression *inExpression, OutputStream *inOutputStream ) { int numBytes = 0; long expressionID = inExpression->getID(); // write the expression ID numBytes += inOutputStream->writeLong( expressionID ); // first, deal with constant case if( expressionID == ConstantExpression::staticGetID() ) { // write the constant ConstantExpression *c = (ConstantExpression *)inExpression; numBytes += inOutputStream->writeDouble( c->getValue() ); } else if( expressionID == FixedConstantExpression::staticGetID() ) { // write the constant FixedConstantExpression *c = (FixedConstantExpression *)inExpression; numBytes += inOutputStream->writeDouble( c->getValue() ); } // next deal with the multi-argument case else if( expressionID == MultiConstantArgumentExpression::staticGetID() ) { MultiConstantArgumentExpression *m = (MultiConstantArgumentExpression*)inExpression; Expression *wrappedExpression = m->getWrappedExpression(); numBytes += serializeExpression( wrappedExpression, inOutputStream ); } // finally, deal with the general case else { // write each of the expression's arguments in succession for( int i=0; igetNumArguments(); i++ ) { // call serialize recursively numBytes += serializeExpression( inExpression->getArgument( i ), inOutputStream ); } } return numBytes; } inline long ExpressionSerializer::deserializeExpression( Expression **outExpression, InputStream *inInputStream ) { int numBytes = 0; long expressionID; // read the expression ID numBytes += inInputStream->readLong( &expressionID ); // first, deal with constant case if( expressionID == ConstantExpression::staticGetID() ) { double constantValue; numBytes += inInputStream->readDouble( &constantValue ); *outExpression = new ConstantExpression( constantValue ); } else if( expressionID == FixedConstantExpression::staticGetID() ) { double constantValue; numBytes += inInputStream->readDouble( &constantValue ); *outExpression = new FixedConstantExpression( constantValue ); } // next deal with the multi-argument case else if( expressionID == MultiConstantArgumentExpression::staticGetID() ) { // call deserialize recursively Expression *wrappedExpression; numBytes += deserializeExpression( &wrappedExpression, inInputStream ); MultiConstantArgumentExpression *m = new MultiConstantArgumentExpression( wrappedExpression ); *outExpression = (Expression *)m; } // finally, deal with the general case else { // switch based on expression type // note that we can't use switch/case here because // staticGetID doesn't return a constant if( expressionID == InvertExpression::staticGetID() ) { *outExpression = new InvertExpression( NULL ); } else if( expressionID == NegateExpression::staticGetID() ) { *outExpression = new NegateExpression( NULL ); } else if( expressionID == PowerExpression::staticGetID() ) { *outExpression = new PowerExpression( NULL, NULL ); } else if( expressionID == ProductExpression::staticGetID() ) { *outExpression = new ProductExpression( NULL, NULL ); } else if( expressionID == SinExpression::staticGetID() ) { *outExpression = new SinExpression( NULL ); } else if( expressionID == SumExpression::staticGetID() ) { *outExpression = new SumExpression( NULL, NULL ); } else { printf( "Unknown expression type %d read from stream\n", expressionID ); // default to a constant expression of 0 *outExpression = new ConstantExpression( 0 ); } // now deserialize the arguments // read each of the expression's arguments in succession for( int i=0; i<(*outExpression)->getNumArguments(); i++ ) { // call deserialize recursively Expression *argument; numBytes += deserializeExpression( &argument, inInputStream ); // set the argument into our expression (*outExpression)->setArgument( i, argument ); } } // end non-constant case return numBytes; } #endif between-6+dfsg1.orig/minorGems/math/geometry/0000750000175000017500000000000011435543335017772 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/math/geometry/Angle3D.h0000640000175000017500000001106711435543335021366 0ustar pabspabs/* * Modification History * * 2000-December-13 Jason Rohrer * Created. * * 2000-December-14 Jason Rohrer * Added data members and constructors. * * 2001-January-10 Jason Rohrer * Made class serializable. * * 2001-January-15 Jason Rohrer * Added a print() function. * * 2001-February-10 Jason Rohrer * Added a linear sum function. * * 2001-March-11 Jason Rohrer * Added a scale function. * * 2004-February-13 Jason Rohrer * Added setComponents functions. * * 2006-September-3 Jason Rohrer * Added zero-angle constructor. */ #ifndef ANGLE_3D_INCLUDED #define ANGLE_3D_INCLUDED #include #include "minorGems/io/Serializable.h" /** * Angle in 3-space. * * @author Jason Rohrer */ class Angle3D : public Serializable { public: // rotations in radians around x, y, and z axis double mX, mY, mZ; /** * Constructs an Angle3D. */ Angle3D( double inX, double inY, double inZ ); /** * Constructs a zero angle. */ Angle3D(); /** * Constructs an Angle3D by copying the parameters from * another Angle3D. * * @param inOther angle to copy parameters from. */ Angle3D( Angle3D *inOther ); /** * Sets the components of this angle. */ void setComponents( double inX, double inY, double inZ ); /** * Sets components by copying the parameters from * another Angle3D. * * @param inOther vector to copy parameters from. * Must be destroyed by caller. */ void setComponents( Angle3D *inOther ); /** * Sums another angle with this angle. * * @param inOther angle to add to this angle. */ void add( Angle3D *inOther ); /** * Subtracts a angle from this angle. * * @param inOther angle to subtract from this angle. */ void subtract( Angle3D *inOther ); /** * Multiplies this angle by a scalar. * * @param inScalar scalar to multiply this angle by. */ void scale( double inScalar ); /** * Computes the linear weighted sum of two angles. * * @param inFirst the first angle. * @param inSecond the second angle. * @param inFirstWeight the weight given to the first angle in the * sum. The second angle is weighted (1-inFirstWeight). * * @return the sum angle. Must be destroyed by caller. */ static Angle3D *linearSum( Angle3D *inFirst, Angle3D *inSecond, double inFirstWeight ); /** * Prints this angle to standard out. */ void print(); // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); }; inline Angle3D::Angle3D( double inX, double inY, double inZ ) : mX( inX ), mY( inY ), mZ( inZ ) { } inline Angle3D::Angle3D() : mX( 0 ), mY( 0 ), mZ( 0 ) { } inline Angle3D::Angle3D( Angle3D *inOther ) : mX( inOther->mX ), mY( inOther->mY ), mZ( inOther->mZ ) { } inline void Angle3D::setComponents( double inX, double inY, double inZ ) { mX = inX; mY = inY; mZ = inZ; } inline void Angle3D::setComponents( Angle3D *inOther ) { setComponents( inOther->mX, inOther->mY, inOther->mZ ); } inline void Angle3D::add( Angle3D *inOther ) { mX += inOther->mX; mY += inOther->mY; mZ += inOther->mZ; } inline void Angle3D::subtract( Angle3D *inOther ) { mX -= inOther->mX; mY -= inOther->mY; mZ -= inOther->mZ; } inline void Angle3D::scale( double inScalar ) { mX *= inScalar; mY *= inScalar; mZ *= inScalar; } inline Angle3D *Angle3D::linearSum( Angle3D *inFirst, Angle3D *inSecond, double inFirstWeight ) { double secondWeight = 1 - inFirstWeight; double x = inFirstWeight * inFirst->mX + secondWeight * inSecond->mX; double y = inFirstWeight * inFirst->mY + secondWeight * inSecond->mY; double z = inFirstWeight * inFirst->mZ + secondWeight * inSecond->mZ; return new Angle3D( x, y, z ); } inline int Angle3D::serialize( OutputStream *inOutputStream ) { int numBytes = 0; numBytes += inOutputStream->writeDouble( mX ); numBytes += inOutputStream->writeDouble( mY ); numBytes += inOutputStream->writeDouble( mZ ); return numBytes; } inline int Angle3D::deserialize( InputStream *inInputStream ) { int numBytes = 0; numBytes += inInputStream->readDouble( &( mX ) ); numBytes += inInputStream->readDouble( &( mY ) ); numBytes += inInputStream->readDouble( &( mZ ) ); return numBytes; } inline void Angle3D::print() { printf( "(%f, %f, %f)", mX, mY, mZ ); } #endif between-6+dfsg1.orig/minorGems/math/geometry/Transform3D.h0000640000175000017500000001757311435543335022323 0ustar pabspabs/* * Modification History * * 2001-January-16 Jason Rohrer * Created. * Added a missing getMatrix() function. * * 2001-February-3 Jason Rohrer * Updated serialization code to use new interfaces. */ #ifndef TRANSFORM_3D_INCLUDED #define TRANSFORM_3D_INCLUDED #include #include #include "minorGems/io/Serializable.h" #include "Vector3D.h" #include "Angle3D.h" /** * An affine transformation in 3D. * * @author Jason Rohrer */ class Transform3D : public Serializable { public: /** * Creates a new identity transform. */ Transform3D(); /** * Creates a new transform by copying another transform. * * @param inOther the transform to copy. */ Transform3D( Transform3D *inOther ); /** * Adds a rotation to the end of this transform. Note that the * rotations specified by inAngle are applied in the following order: * rotX, rotY, rotZ * * @param inAngle angle rotation to add. Must be destructed by caller. */ void rotate( Angle3D *inAngle ); /** * Adds a scaling operation to the end of this transform. * * @param inScale the uniform scale factor. */ void scale( double inScale ); /** * Adds a scaling operation to the end of this transform. * * @param inScaleX the x direction scale factor. * @param inScaleY the y direction scale factor. * @param inScaleZ the z direction scale factor. */ void scale( double inScaleX, double inScaleY, double inScaleZ ); /** * Adds a translation to the end of this transform. * * @param inTranslation angle rotation to add. * Must be destructed by caller. */ void translate( Vector3D *inTranslation ); /** * Adds a transformation to the end of this transformation. * * @param inTransform the transform to add. inTransform is no * modified by this call, and must be destroyed by the caller. */ void transform( Transform3D *inTransform ); /** * Transforms a vector using the built-up transformation. * * @param inTarget the vector to transform. The object passed * in is modified directly, and must be destroyed by the caller. */ void apply( Vector3D *inTarget ); /** * Transforms a vector using the built-up transformation, but skips * the translation part of the transform. This is useful when * applying the transform to normals, when translations will screw * them up. * * @param inTarget the vector to transform. The object passed * in is modified directly, and must be destroyed by the caller. */ void applyNoTranslation( Vector3D *inTarget ); /** * Gets the transformation matrix underlying this transform. * * @return the transformation matrix. */ double *getMatrix(); /** * Prints the transformation matrix to standard out. */ void print(); // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); private: double mMatrix[4][4]; /** * Multiplies mMatrix by inMatrix, i.e., mMatrix = inMatrix * mMatrix. * * Note that this reversed multiplication order works for concatonating * transformation matrices when we're using column vectors for our 3D * points. Thus, if after the above operation, we compute: * point = mMatrix * point, * we will be transformping point first by the original * mMatrix and then by inMatrix. * * @param inMatrix the matrix to multiply mMatrix by. */ void multiply( double inMatrix[][4] ); /** * Multiplies inMatrixA by inMatrixB, i.e., * inMatrixA = inMatrixA * inMatrixB. * * @param inMatrixA the first matrix in the multiplication, and * the destination of the result. * @param inMatrixB the second matrix in the multiplication. */ //void multiply( double[4][4] inMatrixA, double[4][4] inMatrixB ); }; inline Transform3D::Transform3D() { double tempM[4][4] = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; memcpy( mMatrix, tempM, 16 * sizeof( double ) ); } inline Transform3D::Transform3D( Transform3D *inOther ) { memcpy( mMatrix, inOther->getMatrix(), 16 * sizeof( double ) ); } inline void Transform3D::rotate( Angle3D *inAngle ) { double aX = inAngle->mX; double rotX[4][4] = { { 1, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 1 } }; rotX[1][1] = cos( aX ); rotX[1][2] = -sin( aX ); rotX[2][1] = sin( aX ); rotX[2][2] = cos( aX ); double aY = inAngle->mY; double rotY[4][4] = { { 0, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 1 } }; rotY[0][0] = cos( aY ); rotY[0][2] = sin( aY ); rotY[2][0] = -sin( aY ); rotY[2][2] = cos( aY ); double aZ = inAngle->mZ; double rotZ[4][4] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; rotZ[0][0] = cos( aZ ); rotZ[0][1] = -sin( aZ ); rotZ[1][0] = sin( aZ ); rotZ[1][1] = cos( aZ ); multiply( rotX ); multiply( rotY ); multiply( rotZ ); } inline void Transform3D::scale( double inScale ) { scale( inScale, inScale, inScale ); } inline void Transform3D::scale( double inScaleX, double inScaleY, double inScaleZ ) { double scaleM[4][4] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 1 } }; scaleM[0][0] = inScaleX; scaleM[1][1] = inScaleY; scaleM[2][2] = inScaleZ; multiply( scaleM ); } inline void Transform3D::translate( Vector3D *inTranslation ) { double translateM[4][4] = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; translateM[0][3] = inTranslation->mX; translateM[1][3] = inTranslation->mY; translateM[2][3] = inTranslation->mZ; multiply( translateM ); } inline void Transform3D::transform( Transform3D *inTransform ) { double tempM[4][4]; memcpy( tempM, inTransform->getMatrix(), 16 * sizeof( double ) ); multiply( tempM ); } inline void Transform3D::apply( Vector3D *inTarget ) { double x = inTarget->mX; double y = inTarget->mY; double z = inTarget->mZ; inTarget->mX = mMatrix[0][0] * x + mMatrix[0][1] * y + mMatrix[0][2] * z + mMatrix[0][3]; inTarget->mY = mMatrix[1][0] * x + mMatrix[1][1] * y + mMatrix[1][2] * z + mMatrix[1][3]; inTarget->mZ = mMatrix[2][0] * x + mMatrix[2][1] * y + mMatrix[2][2] * z + mMatrix[2][3]; } inline void Transform3D::applyNoTranslation( Vector3D *inTarget ) { double x = inTarget->mX; double y = inTarget->mY; double z = inTarget->mZ; inTarget->mX = mMatrix[0][0] * x + mMatrix[0][1] * y + mMatrix[0][2] * z; inTarget->mY = mMatrix[1][0] * x + mMatrix[1][1] * y + mMatrix[1][2] * z; inTarget->mZ = mMatrix[2][0] * x + mMatrix[2][1] * y + mMatrix[2][2] * z; } inline void Transform3D::multiply( double inMatrix[][4] ) { double destM[4][4]; for( int dY=0; dY<4; dY++ ) { for( int dX=0; dX<4; dX++ ) { // take a row of inMatrix corresponding to dY // take a column of mMatrix corresponding to dX destM[dY][dX] = 0; for( int i=0; i<4; i++ ) { destM[dY][dX] += inMatrix[dY][i] * mMatrix[i][dX]; } } } memcpy( mMatrix, destM, 16 * sizeof( double ) ); } inline double *Transform3D::getMatrix() { return &( mMatrix[0][0] ); } inline void Transform3D::print() { for( int y=0; y<4; y++ ) { for( int x=0; x<4; x++ ) { printf( "%f ", mMatrix[y][x] ); } printf( "\n" ); } } inline int Transform3D::serialize( OutputStream *inOutputStream ) { int numBytes = 0; for( int y=0; y<4; y++ ) { for( int x=0; x<4; x++ ) { numBytes += inOutputStream->writeDouble( mMatrix[y][x] ); } } return numBytes; } inline int Transform3D::deserialize( InputStream *inInputStream ) { int numBytes = 0; for( int y=0; y<4; y++ ) { for( int x=0; x<4; x++ ) { numBytes += inInputStream->readDouble( &( mMatrix[y][x] ) ); } } return numBytes; } #endif between-6+dfsg1.orig/minorGems/math/geometry/GeometricObject3D.h0000640000175000017500000000230611435543335023401 0ustar pabspabs/* * Modification History * * 2000-December-13 Jason Rohrer * Created. * * 2000-December-13 Jason Rohrer * Added scale() and copy() functions. */ #ifndef GEOMETRIC_OBJECT_3D_INCLUDED #define GEOMETRIC_OBJECT_3D_INCLUDED #include "Vector3D.h" /** * Interface for any geometric objects in 3-space. * * @author Jason Rohrer */ class GeometricObject3D { public: /** * Moves the object. * * @param inVector a non-normalized vector describing the motion * of the object. */ virtual void move( Vector3D *inVector ) = 0; /** * Rotates the object about the origin. * * @param inAngle the angle to rotate the object by. */ virtual void rotate( Angle3D *inAngle ) = 0; /** * Rotates the object about the origin in reverse direction. * * @param inAngle the angle to rotate the object by * in reverse direction. */ virtual void reverseRotate( Angle3D *inAngle ) = 0; /** * Scales the object about the origin. * * @param inScalar value by which to scale. */ virtual void scale( double inScalar ) = 0; /** * Makes an identical copy of this geometric object. */ virtual GeometricObject3D *copy() = 0; }; #endif between-6+dfsg1.orig/minorGems/math/geometry/Triangle3D.h0000640000175000017500000001710511435543335022104 0ustar pabspabs/* * Modification History * * 2001-April-14 Jason Rohrer * Created. * * 2005-February-15 Jason Rohrer * Made destructor virtual to quell warnings. */ #ifndef TRIANGLE_3D_INCLUDED #define TRIANGLE_3D_INCLUDED #include "GeometricObject3D.h" #include "LineSegment3D.h" #include "minorGems/io/Serializable.h" #include #include #ifndef M_PI #define M_PI 3.14159265358979323846 #endif /** * Triangle (in 3-space). * * @author Jason Rohrer */ class Triangle3D : public GeometricObject3D, public Serializable { public: Vector3D *mPoints[3]; /** * Constructs a triangle. * * The vectors are copied, so the caller * is responsible for deallocating the passed in vectors. * * @param inPointA the first point. * @param inPointB the second point. * @param inPointC the third point. * * The "front" face of this trangle is defined as the face * viewed when the above vertices are in counter-clockwise order. */ Triangle3D( Vector3D *inPointA, Vector3D *inPointB, Vector3D *inPointC); /** * Constructs a triangle by copying parameters * from another triangle. * * @param inOtherTriangle the triangle to copy. */ Triangle3D( Triangle3D *inOtherTriangle ); virtual ~Triangle3D(); /** * Gets a line segment from this triangle. * * @param inIndex the line segment to get, in [0,2]. * * @return a new line segment, or NULL if the index is out of range. * Must be destroyed by caller. */ LineSegment3D *getLineSegment( int inIndex ); /** * Gets the normal for the plane containing this triangle. * * @return the normal vector. Must be destroyed by caller. */ Vector3D *getNormal(); /** * Computes the normal projection of a point onto the plane * defined by this triangle. A point is returned even * if it is not inside the bounds of the triangle. * * @param inPoint the point to project. Must be destroyed by caller. * * @return a new vector representing the projection of the point. * Must be destroyed by caller. */ Vector3D *projectOntoPlane( Vector3D *inPoint ); /** * Checks if a point is inside the bounds of this triangle. * * @param inPoint the point to check. Must be destroyed by caller. * * @return true iff the point is in bounds. */ char isInBounds( Vector3D *inPoint ); // these implement the GeometricObject3D interface void move( Vector3D *inVector ); void rotate( Angle3D *inAngle ); void reverseRotate( Angle3D *inAngle ); void scale( double inScalar ); GeometricObject3D *copy(); // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); }; inline Triangle3D::Triangle3D( Vector3D *inEndpointA, Vector3D *inEndpointB, Vector3D *inEndpointC ) { mPoints[0] = new Vector3D( inEndpointA ); mPoints[1] = new Vector3D( inEndpointB ); mPoints[2] = new Vector3D( inEndpointC ); } inline Triangle3D::Triangle3D( Triangle3D *inOtherTriangle ) { mPoints[0] = new Vector3D( inOtherTriangle->mPoints[0] ); mPoints[1] = new Vector3D( inOtherTriangle->mPoints[1] ); mPoints[2] = new Vector3D( inOtherTriangle->mPoints[2] ); } inline Triangle3D::~Triangle3D() { delete mPoints[0]; delete mPoints[1]; delete mPoints[2]; } inline LineSegment3D *Triangle3D::getLineSegment( int inIndex ) { if( inIndex < 0 || inIndex > 2 ) { return NULL; } else { // can pass in mPoints directly, since constructor copies them return new LineSegment3D( mPoints[inIndex], mPoints[ ( inIndex + 1 ) % 2 ] ); } } inline Vector3D *Triangle3D::getNormal() { // cross C-B with A-B to get a normal pointing towards // the viewer when seeing the points in counter-clockwise order Vector3D *firstLeg = new Vector3D( mPoints[2] ); firstLeg->subtract( mPoints[1] ); Vector3D *secondLeg = new Vector3D( mPoints[0] ); secondLeg->subtract( mPoints[1] ); Vector3D *normal = firstLeg->cross( secondLeg ); normal->normalize(); delete firstLeg; delete secondLeg; return normal; } inline Vector3D *Triangle3D::projectOntoPlane( Vector3D *inPoint ) { // formula found at: // http://astronomy.swin.edu.au/pbourke/geometry/pointplane/ //minimum distance = //(A (xa - xb) + B (ya - yb) + C (za - zb)) / sqrt(A^2 + B^2 + C^2) Vector3D *normal = getNormal(); double minDistance = normal->mX * ( inPoint->mX - mPoints[0]->mX ) + normal->mY * ( inPoint->mY - mPoints[0]->mY ) + normal->mZ * ( inPoint->mZ - mPoints[0]->mZ ); minDistance = minDistance / sqrt( normal->mX * normal->mX + normal->mY * normal->mY + normal->mZ * normal->mZ ); double dot = inPoint->dot( normal ); Vector3D *returnPoint = new Vector3D( inPoint ); if( dot > 0 ) { // inPoint on front side of plane normal->scale( -minDistance ); } else { // inPoint on back side of plane normal->scale( minDistance ); } returnPoint->add( normal ); delete normal; return returnPoint; } inline char Triangle3D::isInBounds( Vector3D *inPoint ) { // this is a nice formula, found at // http://astronomy.swin.edu.au/pbourke/geometry/insidepoly/ // compute the angle between inPoint and every pair of points in the // triangle (each edge). If the sum is 2*pi, then the point // is inside the triangle. // note that we have a hard-coded epsilon value here double epsilon = 0.000001; double angleSum = 0; Vector3D *firstLeg = new Vector3D( mPoints[0] ); firstLeg->subtract( inPoint ); Vector3D *secondLeg = new Vector3D( mPoints[1] ); secondLeg->subtract( inPoint ); Vector3D *thirdLeg = new Vector3D( mPoints[2] ); thirdLeg->subtract( inPoint ); angleSum += acos( firstLeg->dot( secondLeg ) / ( firstLeg->getLength() * secondLeg->getLength() ) ); angleSum += acos( secondLeg->dot( thirdLeg ) / ( secondLeg->getLength() * thirdLeg->getLength() ) ); angleSum += acos( thirdLeg->dot( firstLeg ) / ( thirdLeg->getLength() * firstLeg->getLength() ) ); delete firstLeg; delete secondLeg; delete thirdLeg; if( angleSum < ( 2 * M_PI - epsilon ) ) { // angle too small for point to be inside plane return false; } else { return true; } } inline void Triangle3D::move( Vector3D *inVector ) { mPoints[0]->add( inVector ); mPoints[1]->add( inVector ); mPoints[2]->add( inVector ); } inline void Triangle3D::rotate( Angle3D *inAngle ) { mPoints[0]->rotate( inAngle ); mPoints[1]->rotate( inAngle ); mPoints[2]->rotate( inAngle ); } inline void Triangle3D::reverseRotate( Angle3D *inAngle ) { mPoints[0]->reverseRotate( inAngle ); mPoints[1]->reverseRotate( inAngle ); mPoints[2]->reverseRotate( inAngle ); } inline void Triangle3D::scale( double inScalar ) { mPoints[0]->scale( inScalar ); mPoints[1]->scale( inScalar ); mPoints[2]->scale( inScalar ); } inline GeometricObject3D *Triangle3D::copy() { Triangle3D *copiedTriangle = new Triangle3D( this ); return (GeometricObject3D*)copiedTriangle; } inline int Triangle3D::serialize( OutputStream *inOutputStream ) { int numBytesWritten = 0; numBytesWritten += mPoints[0]->serialize( inOutputStream ); numBytesWritten += mPoints[1]->serialize( inOutputStream ); numBytesWritten += mPoints[2]->serialize( inOutputStream ); return numBytesWritten; } inline int Triangle3D::deserialize( InputStream *inInputStream ) { int numBytesRead = 0; numBytesRead += mPoints[0]->deserialize( inInputStream ); numBytesRead += mPoints[1]->deserialize( inInputStream ); numBytesRead += mPoints[2]->deserialize( inInputStream ); return numBytesRead; } #endif between-6+dfsg1.orig/minorGems/math/geometry/Vector3D.h0000640000175000017500000004320111435543335021575 0ustar pabspabs/* * Modification History * * 2000-December-13 Jason Rohrer * Created. * * 2000-December-13 Jason Rohrer * Added a function for getting the distance between two vectors. * Added implementations for current functions. * * 2000-December-17 Jason Rohrer * Added a normalize function. * * 2000-December-18 Jason Rohrer * Added a print function. * Added a length function. * * 2000-December-20 Jason Rohrer * Added a cross product function. * * 2001-January-10 Jason Rohrer * Made class serializable. * * 2001-February-3 Jason Rohrer * Updated serialization code to use new interfaces. * * 2001-February-10 Jason Rohrer * Added a linear sum function. * * 2003-June-20 Jason Rohrer * Added function for getting Z angle between vectors. * * 2005-February-4 Jason Rohrer * Added setCoordinates functions. * * 2005-February-6 Jason Rohrer * Added equals function. * * 2005-February-15 Jason Rohrer * Added function for getting Y angle between vectors. * * 2005-February-22 Jason Rohrer * Added function for getting X angle between vectors. * Added function for rotating about an arbitrary axis. * * 2005-February-25 Jason Rohrer * Fixed bugs in get_AngleTo functions when vectors are close to equal. * * 2005-February-28 Jason Rohrer * Fixed bug in getXAngleTo. * Fixed bugs in get_AngleTo functions when vectors are close to opposite. * * 2005-March-3 Jason Rohrer * Fixed bug in getAngleTo when vectors are close to equal or opposite. * * 2005-March-18 Jason Rohrer * Added a getXZDistance function. * * 2006-August-6 Jason Rohrer * Added a no-arg constructor. */ #ifndef VECTOR_3D_INCLUDED #define VECTOR_3D_INCLUDED #include #include #include "Angle3D.h" #include "minorGems/io/Serializable.h" /** * Geometric vector in 3-space. * * @author Jason Rohrer */ class Vector3D : public Serializable { public: double mX, mY, mZ; /** * Constructs a Vector3D. */ Vector3D( double inX, double inY, double inZ ); /** * Constructs a zero-filled Vector3D. */ Vector3D(); /** * Constructs a Vector3D by copying the parameters from * another Vector3D. * * @param inOther vector to copy parameters from. */ Vector3D( Vector3D *inOther ); /** * Sets the values in this vector */ void setCoordinates( double inX, double inY, double inZ ); /** * Sets coordinates by copying the parameters from * another Vector3D. * * @param inOther vector to copy parameters from. * Must be destroyed by caller. */ void setCoordinates( Vector3D *inOther ); /** * Normalizes this vector so that it has a length of 1. */ void normalize(); /** * Tests if another vector is equal to this vector. * * @param inOther vector to test for equality with this vector. * * @return true if equal, false if not. */ char equals( Vector3D *inOther ); /** * Sums another vector with this vector. * * @param inOther vector to add to this vector. */ void add( Vector3D *inOther ); /** * Subtracts a vector from this vector. * * @param inOther vector to subtract from this vector. */ void subtract( Vector3D *inOther ); /** * Computes a dot product of this vector with another. * * @param inOther vector to perform the dot product with. * * @return the dot product of the two vectors. */ double dot( Vector3D *inOther ); /** * Computes a cross product of this vector with another * ( this x other ). The cross computed is right handed. * * @param inOther vector to perform the cross product with. * * @return the cross product of the two vectors. Must be * destroyed by caller. */ Vector3D *cross( Vector3D *inOther ); /** * Computes the angle between this vector and another vector. * * @param inOther vector to find the angle to. * * @return the angle between the two vectors in radians. * This angle is around the axis given by the cross of the two * vectors. * Must be destroyed by caller. */ double getAngleTo( Vector3D *inOther ); /** * Rotates this vector around an arbitrary axis. * * @param inAxis the axis of rotation. Must be normalized. * Must be destroyed by caller. * @param the angle in radians. */ void rotate( Vector3D *inAxis, double inAngle ); /** * Computes the angle between this vector and another vector in * the x-y plane (in other words, the z-axis rotation angle). * * @param inOther vector to find the angle to. * * @return the angle between the two vectors in the x-y plane. * Must be destroyed by caller. */ Angle3D *getZAngleTo( Vector3D *inOther ); /** * Computes the angle between this vector and another vector in * the x-z plane (in other words, the y-axis rotation angle). * * @param inOther vector to find the angle to. * * @return the angle between the two vectors in the x-z plane. * Must be destroyed by caller. */ Angle3D *getYAngleTo( Vector3D *inOther ); /** * Computes the angle between this vector and another vector in * the y-z plane (in other words, the x-axis rotation angle). * * @param inOther vector to find the angle to. * * @return the angle between the two vectors in the y-z plane. * Must be destroyed by caller. */ Angle3D *getXAngleTo( Vector3D *inOther ); /** * Computes the linear weighted sum of two vectors. * * @param inFirst the first vector. * @param inSecond the second vector. * @param inFirstWeight the weight given to the first vector in the * sum. The second vector is weighted (1-inFirstWeight). * * @return the sum vector. Must be destroyed by caller. */ static Vector3D *linearSum( Vector3D *inFirst, Vector3D *inSecond, double inFirstWeight ); /** * Gets the length of this vector. * * @return this vector's length. */ double getLength(); /** * Multiplies this vector by a scalar. * * @param inScalar scalar to multiply this vector by. */ void scale( double inScalar ); /** * Gets the scalar distance between two vectors. * * @param inOther vector to compute the distance with. * * @return the distance between the two vectors. */ double getDistance( Vector3D *inOther ); /** * Gets the scalar distance between two vectors ignoring the y * components. * * @param inOther vector to compute the distance with. * * @return the xz distance between the two vectors. */ double getXZDistance( Vector3D *inOther ); /** * Rotates the vector about the origin. * * @param inAngle the angle to rotate the vector by. */ void rotate( Angle3D *inAngle ); /** * Rotates the vector about the origin in reverse direction. * * @param inAngle the angle to rotate the object by * in reverse direction. */ void reverseRotate( Angle3D *inAngle ); /** * Prints this vector to standard out. */ void print(); // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); }; inline Vector3D::Vector3D( double inX, double inY, double inZ ) : mX( inX ), mY( inY ), mZ( inZ ) { } inline Vector3D::Vector3D() : mX( 0 ), mY( 0 ), mZ( 0 ) { } inline Vector3D::Vector3D( Vector3D *inOther ) : mX( inOther->mX ), mY( inOther->mY ), mZ( inOther->mZ ) { } inline void Vector3D::setCoordinates( double inX, double inY, double inZ ) { mX = inX; mY = inY; mZ = inZ; } inline void Vector3D::setCoordinates( Vector3D *inOther ) { setCoordinates( inOther->mX, inOther->mY, inOther->mZ ); } inline void Vector3D::normalize() { scale( 1/sqrt( dot( this ) ) ); } inline char Vector3D::equals( Vector3D *inOther ) { return mX == inOther->mX && mY == inOther->mY && mZ == inOther->mZ; } inline void Vector3D::add( Vector3D *inOther ) { mX += inOther->mX; mY += inOther->mY; mZ += inOther->mZ; } inline void Vector3D::subtract( Vector3D *inOther ) { mX -= inOther->mX; mY -= inOther->mY; mZ -= inOther->mZ; } inline double Vector3D::dot( Vector3D *inOther ) { return mX * inOther->mX + mY * inOther->mY + mZ * inOther->mZ; } inline Vector3D *Vector3D::cross( Vector3D *inOther ) { double i = this->mY * inOther->mZ - this->mZ * inOther->mY; double j = this->mZ * inOther->mX - this->mX * inOther->mZ; double k = this->mX * inOther->mY - this->mY * inOther->mX; return new Vector3D( i, j, k ); } inline double Vector3D::getAngleTo( Vector3D *inOther ) { // normalize and remove z component Vector3D *normalThis = new Vector3D( this ); normalThis->normalize(); Vector3D *normalOther = new Vector3D( inOther ); normalOther->normalize(); double cosineOfAngle = normalThis->dot( normalOther ); // cosine is ambiguous (same for negative and positive angles) // compute cross product of vectors // the magnitude of the cross is the sine of the angle between the two // vectors Vector3D *crossVector = normalThis->cross( normalOther ); double sineOfAngle = crossVector->getLength(); delete crossVector; delete normalThis; delete normalOther; double angle = acos( cosineOfAngle ); if( sineOfAngle > 0 ) { angle = -angle; } // if vectors are very close, our dot product above might give // a value greater than 1 due to round-off errors // this causes acos to return NAN if( cosineOfAngle >= 1 ) { angle = 0; } // also need to worry if vectors are complete opposites else if( cosineOfAngle <= -1 ) { angle = M_PI; } return angle; } inline void Vector3D::rotate( Vector3D *inAxis, double inAngle ) { // this formula found here: // http://www.gamedev.net/reference/articles/article1199.asp double c = cos( inAngle ); double s = sin( inAngle ); double t = 1 - c; // we assume inAxis is a unit vector (normalized) double x = inAxis->mX; double y = inAxis->mY; double z = inAxis->mZ; double sx = s * x; double sy = s * y; double sz = s * z; double tx = t * x; double ty = t * y; double txx = tx * x; double txy = tx * y; double txz = tx * z; double tyy = ty * y; double tyz = ty * z; double tzz = t * z * z; /* The rotation matrix is: (txx + c) (txy + sz) (txz - sy) (txy - sz) (tyy + c) (tyz + sx) (txz + sy) (tyz - sx) (tzz + c) */ double newX = (txx + c) * mX + (txy + sz) * mY + (txz - sy) * mZ; double newY = (txy - sz) * mX + (tyy + c) * mY + (tyz + sx) * mZ; double newZ = (txz + sy) * mX + (tyz - sx) * mY + (tzz + c) * mZ; mX = newX; mY = newY; mZ = newZ; } inline Angle3D *Vector3D::getZAngleTo( Vector3D *inOther ) { // normalize and remove z component Vector3D *normalThis = new Vector3D( this ); normalThis->mZ = 0; normalThis->normalize(); Vector3D *normalOther = new Vector3D( inOther ); normalOther->mZ = 0; normalOther->normalize(); double cosineOfZAngle = normalThis->dot( normalOther ); // cosine is ambiguous (same for negative and positive angles) // compute dot product with perpendicular vector to get sine // sign of sine will tell us whether angle is positive or negative Angle3D *rightAngleZ = new Angle3D( 0, 0, M_PI / 2 ); normalThis->rotate( rightAngleZ ); delete rightAngleZ; double sineOfZAngle = normalThis->dot( normalOther ); delete normalThis; delete normalOther; double zAngle = acos( cosineOfZAngle ); if( sineOfZAngle < 0 ) { zAngle = -zAngle; } // if vectors are very close, our dot product above might give // a value greater than 1 due to round-off errors // this causes acos to return NAN if( cosineOfZAngle >= 1 ) { zAngle = 0; } // also need to worry if vectors are complete opposites else if( cosineOfZAngle <= -1 ) { zAngle = M_PI; } return new Angle3D( 0, 0, zAngle ); } inline Angle3D *Vector3D::getYAngleTo( Vector3D *inOther ) { // normalize and remove y component Vector3D *normalThis = new Vector3D( this ); normalThis->mY = 0; normalThis->normalize(); Vector3D *normalOther = new Vector3D( inOther ); normalOther->mY = 0; normalOther->normalize(); double cosineOfYAngle = normalThis->dot( normalOther ); // cosine is ambiguous (same for negative and positive angles) // compute dot product with perpendicular vector to get sine // sign of sine will tell us whether angle is positive or negative Angle3D *rightAngleY = new Angle3D( 0, M_PI / 2, 0 ); normalThis->rotate( rightAngleY ); delete rightAngleY; double sineOfYAngle = normalThis->dot( normalOther ); delete normalThis; delete normalOther; double yAngle = acos( cosineOfYAngle ); if( sineOfYAngle < 0 ) { yAngle = -yAngle; } // if vectors are very close, our dot product above might give // a value greater than 1 due to round-off errors // this causes acos to return NAN if( cosineOfYAngle >= 1 ) { yAngle = 0; } // also need to worry if vectors are complete opposites else if( cosineOfYAngle <= -1 ) { yAngle = M_PI; } return new Angle3D( 0, yAngle, 0 ); } inline Angle3D *Vector3D::getXAngleTo( Vector3D *inOther ) { // normalize and remove y component Vector3D *normalThis = new Vector3D( this ); normalThis->mX = 0; normalThis->normalize(); Vector3D *normalOther = new Vector3D( inOther ); normalOther->mX = 0; normalOther->normalize(); double cosineOfXAngle = normalThis->dot( normalOther ); // cosine is ambiguous (same for negative and positive angles) // compute dot product with perpendicular vector to get sine // sign of sine will tell us whether angle is positive or negative Angle3D *rightAngleX = new Angle3D( M_PI / 2, 0, 0 ); normalThis->rotate( rightAngleX ); delete rightAngleX; double sineOfXAngle = normalThis->dot( normalOther ); delete normalThis; delete normalOther; double xAngle = acos( cosineOfXAngle ); if( sineOfXAngle < 0 ) { xAngle = -xAngle; } // if vectors are very close, our dot product above might give // a value greater than 1 due to round-off errors // this causes acos to return NAN if( cosineOfXAngle >= 1 ) { xAngle = 0; } // also need to worry if vectors are complete opposites else if( cosineOfXAngle <= -1 ) { xAngle = M_PI; } return new Angle3D( xAngle, 0, 0 ); } inline Vector3D *Vector3D::linearSum( Vector3D *inFirst, Vector3D *inSecond, double inFirstWeight ) { double secondWeight = 1 - inFirstWeight; double x = inFirstWeight * inFirst->mX + secondWeight * inSecond->mX; double y = inFirstWeight * inFirst->mY + secondWeight * inSecond->mY; double z = inFirstWeight * inFirst->mZ + secondWeight * inSecond->mZ; return new Vector3D( x, y, z ); } inline double Vector3D::getLength() { return sqrt( dot( this ) ); } inline void Vector3D::scale( double inScalar ) { mX *= inScalar; mY *= inScalar; mZ *= inScalar; } inline double Vector3D::getDistance( Vector3D *inOther ) { double delX = mX - inOther->mX; double delY = mY - inOther->mY; double delZ = mZ - inOther->mZ; return sqrt( delX * delX + delY * delY + delZ * delZ ); } inline double Vector3D::getXZDistance( Vector3D *inOther ) { double delX = mX - inOther->mX; double delZ = mZ - inOther->mZ; return sqrt( delX * delX + delZ * delZ ); } inline void Vector3D::rotate( Angle3D *inAngle ) { if( inAngle->mX != 0 ) { double cosTheta = cos( inAngle->mX ); double sinTheta = sin( inAngle->mX ); double oldY = mY; mY = mY * cosTheta - mZ * sinTheta; mZ = oldY * sinTheta + mZ * cosTheta; } if( inAngle->mY != 0 ) { double cosTheta = cos( inAngle->mY ); double sinTheta = sin( inAngle->mY ); double oldX = mX; mX = cosTheta * mX + sinTheta * mZ; mZ = -sinTheta * oldX + cosTheta * mZ; } if( inAngle->mZ != 0 ) { double cosTheta = cos( inAngle->mZ ); double sinTheta = sin( inAngle->mZ ); double oldX = mX; mX = cosTheta * mX - sinTheta * mY; mY = sinTheta * oldX + cosTheta * mY; } } inline void Vector3D::reverseRotate( Angle3D *inAngle ) { Angle3D *actualAngle = new Angle3D( -inAngle->mX, -inAngle->mY, -inAngle->mZ ); rotate( actualAngle ); delete actualAngle; } inline void Vector3D::print() { printf( "(%f, %f, %f)", mX, mY, mZ ); } inline int Vector3D::serialize( OutputStream *inOutputStream ) { int numBytes = 0; numBytes += inOutputStream->writeDouble( mX ); numBytes += inOutputStream->writeDouble( mY ); numBytes += inOutputStream->writeDouble( mZ ); return numBytes; } inline int Vector3D::deserialize( InputStream *inInputStream ) { int numBytes = 0; numBytes += inInputStream->readDouble( &( mX ) ); numBytes += inInputStream->readDouble( &( mY ) ); numBytes += inInputStream->readDouble( &( mZ ) ); return numBytes; } #endif between-6+dfsg1.orig/minorGems/math/geometry/LineSegment3D.h0000640000175000017500000001134711435543335022553 0ustar pabspabs/* * Modification History * * 2001-April-14 Jason Rohrer * Created. * * 2005-February-15 Jason Rohrer * Made destructor virtual to quell warnings. */ #ifndef LINE_SEGMENT_3D_INCLUDED #define LINE_SEGMENT_3D_INCLUDED #include "GeometricObject3D.h" #include "minorGems/io/Serializable.h" #include #include #ifndef M_PI #define M_PI 3.14159265358979323846 #endif /** * Line segment (in 3-space). * * @author Jason Rohrer */ class LineSegment3D : public GeometricObject3D, public Serializable { public: Vector3D *mEndpoints[2]; /** * Constructs a line segment. * * The vectors are copied, so the caller * is responsible for deallocating the passed in vectors. * * @param inEndpointA the first endpoint. * @param inEndpointB the second endpoint. */ LineSegment3D( Vector3D *inEndpointA, Vector3D *inEndpointB ); /** * Constructs a line segment by copying parameters * from another line segment. * * @param inOtherSegment the line segment to copy. */ LineSegment3D( LineSegment3D *inOtherSegment ); virtual ~LineSegment3D(); /** * Gets the projection of a point onto this line segment * * @param inPoint the point to project. Must be destroyed * by caller. * * @return a new vector representing the projected point, or * NULL if the projection is not on this line segment. */ Vector3D *projectPoint( Vector3D *inPoint ); // these implement the GeometricObject3D interface void move( Vector3D *inVector ); void rotate( Angle3D *inAngle ); void reverseRotate( Angle3D *inAngle ); void scale( double inScalar ); GeometricObject3D *copy(); // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); }; inline LineSegment3D::LineSegment3D( Vector3D *inEndpointA, Vector3D *inEndpointB ) { mEndpoints[0] = new Vector3D( inEndpointA ); mEndpoints[1] = new Vector3D( inEndpointB ); } inline LineSegment3D::LineSegment3D( LineSegment3D *inOtherSegment ) { mEndpoints[0] = new Vector3D( inOtherSegment->mEndpoints[0] ); mEndpoints[1] = new Vector3D( inOtherSegment->mEndpoints[1] ); } inline LineSegment3D::~LineSegment3D() { delete mEndpoints[0]; delete mEndpoints[1]; } inline Vector3D *LineSegment3D::projectPoint( Vector3D *inPoint ) { // compute the vector for the underlying line of this segment Vector3D *supportingVector = new Vector3D( mEndpoints[0] ); supportingVector->subtract( mEndpoints[1] ); supportingVector->normalize(); // now find the lengths of the projection of each endpoint // onto this supporting vector double lengthA = supportingVector->dot( mEndpoints[0] ); double lengthB = supportingVector->dot( mEndpoints[1] ); // find the length of the projection of inPoint double lengthInPoint = supportingVector->dot( inPoint ); // projection is off the segment if lengthInPoint is not // between lengthA and lengthB if( lengthInPoint > lengthA && lengthInPoint > lengthB ) { delete supportingVector; return NULL; } else if( lengthInPoint < lengthA && lengthInPoint < lengthB ) { delete supportingVector; return NULL; } else { // length is in between the two // compute difference from A's projection double difference = lengthInPoint - lengthA; Vector3D *returnVector = new Vector3D( mEndpoints[0] ); supportingVector->scale( difference ); returnVector->add( supportingVector ); delete supportingVector; return returnVector; } } inline void LineSegment3D::move( Vector3D *inVector ) { mEndpoints[0]->add( inVector ); mEndpoints[1]->add( inVector ); } inline void LineSegment3D::rotate( Angle3D *inAngle ) { mEndpoints[0]->rotate( inAngle ); mEndpoints[1]->rotate( inAngle ); } inline void LineSegment3D::reverseRotate( Angle3D *inAngle ) { mEndpoints[0]->reverseRotate( inAngle ); mEndpoints[1]->reverseRotate( inAngle ); } inline void LineSegment3D::scale( double inScalar ) { mEndpoints[0]->scale( inScalar ); mEndpoints[1]->scale( inScalar ); } inline GeometricObject3D *LineSegment3D::copy() { LineSegment3D *copiedSegment = new LineSegment3D( this ); return (GeometricObject3D*)copiedSegment; } inline int LineSegment3D::serialize( OutputStream *inOutputStream ) { int numBytesWritten = 0; numBytesWritten += mEndpoints[0]->serialize( inOutputStream ); numBytesWritten += mEndpoints[1]->serialize( inOutputStream ); return numBytesWritten; } inline int LineSegment3D::deserialize( InputStream *inInputStream ) { int numBytesRead = 0; numBytesRead += mEndpoints[0]->deserialize( inInputStream ); numBytesRead += mEndpoints[1]->deserialize( inInputStream ); return numBytesRead; } #endif between-6+dfsg1.orig/minorGems/math/geometry/Sphere.h0000640000175000017500000001702511435543335021377 0ustar pabspabs/* * Modification History * * 2000-December-13 Jason Rohrer * Created. * * 2000-December-14 Jason Rohrer * Added implementation for all member functions. * * 2001-January-10 Jason Rohrer * Made class serializable. * * 2001-January-24 Jason Rohrer * Fixed a bug in the deserialization function. * * 2001-February-2 Jason Rohrer * Added M_PI definition. * * 2001-April-14 Jason Rohrer * Added line segment and triangle intersection tests. */ #ifndef SPHERE_INCLUDED #define SPHERE_INCLUDED #include "GeometricObject3D.h" #include "LineSegment3D.h" #include "Triangle3D.h" #include "minorGems/io/Serializable.h" #include #include #ifndef M_PI #define M_PI 3.14159265358979323846 #endif /** * Geometric sphere (in 3-space). * * @author Jason Rohrer */ class Sphere : public GeometricObject3D, public Serializable { public: Vector3D *mCenter; double mRadius; /** * Constructs a Sphere. * * @param inCenter a vector containing the coordinates of the * sphere's center. The vector is copied, so the caller * is responsible for deallocating the passed in vector. * * @param inRadius the radius of the sphere. */ Sphere( Vector3D *inCenter, double inRadius ); /** * Constructs a Sphere by copying parameters from another Sphere. * * @param inOtherSphere the sphere to copy. */ Sphere( Sphere *inOtherSphere ); ~Sphere(); /** * Gets whether this sphere intersects with another. * * @param inOtherSphere the sphere to test for intersection * with this sphere. * * @return true iff this sphere intersects with the other. */ char intersects( Sphere *inOtherSphere ); /** * Gets the normalized direction of intersection of this * sphere with another. * * @param inOtherSphere the sphere to test for intersection * with this sphere. * * @return a normalized vector direction of the intersection, * or NULL if there is no intersection. */ Vector3D *getIntersection( Sphere *inOtherSphere ); /** * Gets whether a line segment intersects or is inside this sphere. * * @param inSegment the segment to test. * * @return true if the segment intersects with or is contained by * this sphere. */ char intersects( LineSegment3D *inSegment ); /** * Gets whether a triangle intesects or is inside this sphere. * * * @param inTriangle the triangle to test. * * @return true if the triangle intersects with or is contained by * this sphere. */ char intersects( Triangle3D *inTriangle ); /** * Gets the volume of this sphere. * * @return the volume of this sphere. */ double getVolume(); // these implement the GeometricObject3D interface void move( Vector3D *inVector ); void rotate( Angle3D *inAngle ); void reverseRotate( Angle3D *inAngle ); void scale( double inScalar ); GeometricObject3D *copy(); // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); }; inline Sphere::Sphere( Vector3D *inCenter, double inRadius ) : mCenter( new Vector3D( inCenter ) ), mRadius( inRadius ) { } inline Sphere::Sphere( Sphere *inOtherSphere ) : mCenter( new Vector3D( inOtherSphere->mCenter ) ), mRadius( inOtherSphere->mRadius ) { } inline Sphere::~Sphere() { delete mCenter; } inline char Sphere::intersects( Sphere *inOtherSphere ) { double distance = mCenter->getDistance( inOtherSphere->mCenter ); if( distance <= mRadius + inOtherSphere->mRadius ) { return true; } else { return false; } } inline Vector3D *Sphere::getIntersection( Sphere *inOtherSphere ) { if( intersects( inOtherSphere ) ) { Vector3D * returnVector = new Vector3D( inOtherSphere->mCenter ); returnVector->subtract( mCenter ); returnVector->normalize(); return returnVector; } else { return NULL; } } /* * These intersection algorithms were found in the following paper: * * ERIT -- A Collection of Efficient and Reliable Intersection Tests * by Martin Held * Journal of Graphics Tools */ inline char Sphere::intersects( LineSegment3D *inSegment ) { // first check if either endpoint is inside this sphere if( inSegment->mEndpoints[0]->getDistance( mCenter ) <= mRadius ) { return true; } else if( inSegment->mEndpoints[1]->getDistance( mCenter ) <= mRadius ) { return true; } else { // both endpoints outside // project center onto the line Vector3D *projectedCenter = inSegment->projectPoint( mCenter ); if( projectedCenter == NULL ) { // projection is outside of the segment return false; } else { // projection is inside of the segment // check distance from center double distance = projectedCenter->getDistance( mCenter ); delete projectedCenter; if( distance <= mRadius ) { return true; } else { return false; } } } } inline char Sphere::intersects( Triangle3D *inTriangle ) { char intersectionFound; // first, check each triangle edge segment for intersection LineSegment3D *segmentA = inTriangle->getLineSegment( 0 ); intersectionFound = intersects( segmentA ); delete segmentA; if( intersectionFound ) { return true; } LineSegment3D *segmentB = inTriangle->getLineSegment( 1 ); intersectionFound = intersects( segmentB ); delete segmentB; if( intersectionFound ) { return true; } LineSegment3D *segmentC = inTriangle->getLineSegment( 2 ); intersectionFound = intersects( segmentC ); delete segmentC; if( intersectionFound ) { return true; } // if we're at this point, none of the edges intersected. // we still need to check if the interior region of the triangle // is inside the sphere Vector3D *projectedCenter = inTriangle->projectOntoPlane( mCenter ); if( inTriangle->isInBounds( projectedCenter ) ) { if( projectedCenter->getDistance( mCenter ) <= mRadius ) { // the projected center is inside the triangle and // inside the sphere intersectionFound = true; } else { // the projected center is inside the triangle, but outside // the sphere intersectionFound = false; } } else { // center projection not even in triangle bounds, so no intersection intersectionFound = false; } delete projectedCenter; return intersectionFound; } inline double Sphere::getVolume() { return (4/3) * M_PI * mRadius * mRadius * mRadius; } inline void Sphere::move( Vector3D *inVector ) { mCenter->add( inVector ); } inline void Sphere::rotate( Angle3D *inAngle ) { mCenter->rotate( inAngle ); } inline void Sphere::reverseRotate( Angle3D *inAngle ) { mCenter->reverseRotate( inAngle ); } inline void Sphere::scale( double inScalar ) { mCenter->scale( inScalar ); mRadius *= inScalar; } inline GeometricObject3D *Sphere::copy() { Sphere *copiedSphere = new Sphere( this ); return (GeometricObject3D*)copiedSphere; } inline int Sphere::serialize( OutputStream *inOutputStream ) { int numBytesWritten = 0; numBytesWritten += mCenter->serialize( inOutputStream ); unsigned char* doublePointer = (unsigned char *)( &mRadius ); numBytesWritten += inOutputStream->write( doublePointer, sizeof( double ) ); return numBytesWritten; } inline int Sphere::deserialize( InputStream *inInputStream ) { int numBytesRead = 0; numBytesRead += mCenter->deserialize( inInputStream ); unsigned char* doublePointer = (unsigned char *)( &mRadius ); numBytesRead += inInputStream->read( doublePointer, sizeof( double ) ); return numBytesRead; } #endif between-6+dfsg1.orig/minorGems/math/probability/0000750000175000017500000000000011435543335020457 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/math/probability/ProbabilityMassFunction.h0000640000175000017500000002034711435543335025451 0ustar pabspabs/* * Modification History * * 2001-November-17 Jason Rohrer * Created. * Added a constructor for explicit initialization of elements. * Made serializable. * * 2001-November-18 Jason Rohrer * Added function for finding the minimum probability value. * Added a print function. */ #ifndef PROBABILITY_MASS_FUNCTION_INCLUDED #define PROBABILITY_MASS_FUNCTION_INCLUDED #include "minorGems/util/SimpleVector.h" #include "minorGems/util/random/RandomSource.h" #include "minorGems/io/Serializable.h" /** * A discrete probability distribution. * All probabilities are constrained to sum to 1. * * @author Jason Rohrer */ class ProbabilityMassFunction : public Serializable { public: /** * Constructs a probability mass function. * * @param inRandSource the random source to use when * sampling from this function. * Must be destroyed by caller after this class is destroyed. */ ProbabilityMassFunction( RandomSource *inRandSource ); /** * Constructs a probability mass function with elements * already inserted. * * @param inRandSource the random source to use when * sampling from this function. * Must be destroyed by caller after this class is destroyed. * @param inNumElements the number of elements * this PMF should be initialized with. * @param inProbabilities the probabilities to start with. * Note that these values will be normalized before * being stored. * Will be destroyed by this constructor. */ ProbabilityMassFunction( RandomSource *inRandSource, int inNumElements, double *inProbabilities ); virtual ~ProbabilityMassFunction(); /** * Adds an element and a probability to * this mass function. * * Note that since the distribution * always sums to 1, inProbability will * be normalized and thus the value set will likely * not exactly equal the value specified by the caller. * * @param inProbability the probability of the new element. * * @return the index of the new element in the distribution/ * Note that the actual index of this element * may change in the future as elements are added to * and removed from this mass function. */ virtual unsigned long addElement( double inProbability ); /** * Removes an element from this mass function. * * @param inIndex the index of the element. */ virtual void removeElement( unsigned long inIndex ); /** * Gets the probability of an element. * * @param inIndex the index of the element. * * @return the probability of the element at inIndex, * or 0 if inIndex is not a valid index. */ virtual double getProbability( unsigned long inIndex ); /** * Sets the probability of an element. * * Note that since the distribution * always sums to 1, inProbability will * be normalized and thus the value set will likely * not exactly equal the value specified by the caller. * * @param inIndex the index of the element. * @param inProbability the probability of the element at inIndex. */ virtual void setProbability( unsigned long inIndex, double inProbability ); /** * Samples an element at random according to this distribution. * * @return the index of the sampled element. */ virtual unsigned long sampleElement(); /** * Gets the minimum probability value of this function. * * @return the minimum probability value. */ virtual double getMinimumProbability(); /** * Prints the probabilities in this mass function to standard out. */ virtual void print(); // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); protected: RandomSource *mRandSource; SimpleVector< double > *mProbabilityVector; /** * Normalizes this distribution so that it sums to 1. */ virtual void normalize(); /** * Gets the net sum of this probability distribution. * * @return the sum of this distribution. */ virtual double getProbabilitySum(); }; inline ProbabilityMassFunction::ProbabilityMassFunction( RandomSource *inRandSource ) : mRandSource( inRandSource ), mProbabilityVector( new SimpleVector< double >() ) { } inline ProbabilityMassFunction::ProbabilityMassFunction( RandomSource *inRandSource, int inNumElements, double *inProbabilities ) : mRandSource( inRandSource ), mProbabilityVector( new SimpleVector< double >( inNumElements ) ){ for( int i=0; ipush_back( inProbabilities[i] ); } normalize(); } inline ProbabilityMassFunction::~ProbabilityMassFunction() { // we can simply delete this vector, since its elements are primitives delete mProbabilityVector; } inline unsigned long ProbabilityMassFunction::addElement( double inProbability ) { mProbabilityVector->push_back( inProbability ); normalize(); return mProbabilityVector->size(); } inline void ProbabilityMassFunction::removeElement( unsigned long inIndex ) { mProbabilityVector->deleteElement( (int)inIndex ); normalize(); } inline double ProbabilityMassFunction::getProbability( unsigned long inIndex ) { if( inIndex >= 0 && inIndex < mProbabilityVector->size() ) { return *( mProbabilityVector->getElement( inIndex ) ); } else { return 0; } } inline void ProbabilityMassFunction::setProbability( unsigned long inIndex, double inProbability ) { if( inIndex >= 0 && inIndex < mProbabilityVector->size() ) { *( mProbabilityVector->getElement( inIndex ) ) = inProbability; normalize(); } } inline unsigned long ProbabilityMassFunction::sampleElement() { double randVal = mRandSource->getRandomDouble(); // compute a running CDF value until we surpass randVal double currentCDFVal = 0; int currentIndex = -1; while( currentCDFVal < randVal ) { currentIndex++; double currentProb = *( mProbabilityVector->getElement( currentIndex ) ); currentCDFVal += currentProb; } // when we exit the while loop, we are at the index of the // element whose probability pushed the CDF past randVal if( currentIndex == -1 ) { // randVal was 0 return 0; } else { return currentIndex; } } inline double ProbabilityMassFunction::getMinimumProbability() { // works, since all values <= 1 double minValue = 2; int numElements = mProbabilityVector->size(); for( int i=0; igetElement( i ) ); if( prob < minValue ) { minValue = prob; } } return minValue; } inline void ProbabilityMassFunction::normalize() { double currentSum = getProbabilitySum(); if( currentSum != 1 ) { double invCurrentSum = 1.0 / currentSum; int numElements = mProbabilityVector->size(); for( int i=0; igetElement( i ); *prob = (*prob) * invCurrentSum; } double newSum = getProbabilitySum(); } } inline double ProbabilityMassFunction::getProbabilitySum() { double sum = 0; int numElements = mProbabilityVector->size(); for( int i=0; igetElement( i ) ); } return sum; } inline void ProbabilityMassFunction::print() { long numElements = mProbabilityVector->size(); for( int i=0; igetElement( i ) ); printf( "%lf ", prob ); } } inline int ProbabilityMassFunction::serialize( OutputStream *inOutputStream ) { int numBytes = 0; long numElements = mProbabilityVector->size(); numBytes += inOutputStream->writeLong( numElements ); for( int i=0; iwriteDouble( *( mProbabilityVector->getElement( i ) ) ); } return numBytes; } inline int ProbabilityMassFunction::deserialize( InputStream *inInputStream ) { int numBytes = 0; delete mProbabilityVector; long numElements; numBytes += inInputStream->readLong( &numElements ); mProbabilityVector = new SimpleVector< double >( numElements ); for( int i=0; ireadDouble( &prob ); mProbabilityVector->push_back( prob ); } normalize(); return numBytes; } #endif between-6+dfsg1.orig/minorGems/math/BigInt.cpp0000640000175000017500000003336111435543335020026 0ustar pabspabs/* * Modification History * * 2002-May-25 Jason Rohrer * Created. * Changed to remove extra zeros when subtracting. */ #include "BigInt.h" #include "minorGems/util/stringUtils.h" #include #include BigInt::BigInt( int inSign, int inNumBytes, unsigned char *inBytes ) : mSign( inSign ), mNumBytes( inNumBytes ), mBytes( new unsigned char[ inNumBytes ] ) { memcpy( mBytes, inBytes, mNumBytes ); } BigInt::BigInt( int inInt ) { if( inInt > 0 ) { mSign = 1; } else if( inInt == 0 ) { mSign = 0; } else { mSign = -1; // flip sign so conversion works inInt *= -1; } mNumBytes = 4; int bytesToSkip = 0; int baseFactor = 1; mBytes = new unsigned char[ 4 ]; int i; for( i=mNumBytes-1; i>=mNumBytes-4; i-- ) { mBytes[i] = 0xFF & ( inInt / baseFactor ); baseFactor *= 256; } if( mBytes[0] == 0 ) { bytesToSkip++; if( mBytes[1] == 0 ) { bytesToSkip++; if( mBytes[2] == 0 ) { bytesToSkip++; if( mBytes[3] == 0 ) { bytesToSkip++; } } } } mNumBytes -= bytesToSkip; unsigned char *temp = new unsigned char[ mNumBytes ]; memcpy( temp, &( mBytes[ bytesToSkip ] ), mNumBytes ); delete [] mBytes; mBytes = temp; } BigInt::~BigInt() { delete [] mBytes; } BigInt *BigInt::add( BigInt *inOtherInt ) { //char *stringA = convertToHexString(); //char *stringB = inOtherInt->convertToHexString(); //printf( "Adding %s to %s\n", stringA, stringB ); //delete [] stringA; //delete [] stringB; if( mSign == 0 && inOtherInt->mSign == 0 ) { return getZero(); } else if( mSign == 0 && inOtherInt->mSign != 0 ) { return inOtherInt->copy(); } else if( mSign != 0 && inOtherInt->mSign == 0 ) { return copy(); } else if( mSign == -1 && inOtherInt->mSign == -1 ) { // adding two negatives // add them as positives, then flip sign of result BigInt *copyA = copy(); BigInt *copyB = inOtherInt->copy(); copyA->mSign = 1; copyB->mSign = 1; BigInt *result = copyA->add( copyB ); delete copyA; delete copyB; result->mSign = -1; return result; } else if( mSign == 1 && inOtherInt->mSign == -1 ) { // flip other sign and subtract BigInt *copy = inOtherInt->copy(); copy->mSign = 1; BigInt *result = subtract( copy ); delete copy; return result; } else if( mSign == -1 && inOtherInt->mSign == 1 ) { // flip our sign and subtract BigInt *copy = this->copy(); copy->mSign = 1; BigInt *result = inOtherInt->subtract( copy ); delete copy; return result; } else { // both this int and arg int are positive int maxLength = mNumBytes; if( maxLength < inOtherInt->mNumBytes ) { maxLength = inOtherInt->mNumBytes; } // leave room for carry unsigned char *result = new unsigned char[ maxLength + 1 ]; // flip to little-endian order to make adding easier BigInt *intA = flipByteOrder(); BigInt *intB = inOtherInt->flipByteOrder(); int sum = 0; for( int i=0; imNumBytes ) { byteA = intA->mBytes[i]; } if( i < intB->mNumBytes ) { byteB = intB->mBytes[i]; } // add in high-order bits from last sum sum = byteA + byteB + ( sum >> 8 ); // truncate to low-order bits result[i] = (unsigned char)sum; } // stick remaining carry into last byte result[maxLength] = (unsigned char)( sum >> 8 ); BigInt *resultInt; if( result[maxLength] == 0 ) { // result array will be copied skipping carry byte resultInt = new BigInt( 1, maxLength, result ); } else { // keep carry byte resultInt = new BigInt( 1, maxLength + 1, result ); } BigInt *flippedResult = resultInt->flipByteOrder(); delete intA; delete intB; delete resultInt; delete [] result; return flippedResult; } } BigInt *BigInt::subtract( BigInt *inOtherInt ) { //char *stringA = convertToHexString(); //char *stringB = inOtherInt->convertToHexString(); //printf( "Subtracting %s from %s\n", stringB, stringA ); //delete [] stringA; //delete [] stringB; if( mSign == 0 && inOtherInt->mSign == 0 ) { return getZero(); } else if( mSign != 0 && inOtherInt->mSign == 0 ) { return copy(); } else if( mSign == 0 && inOtherInt->mSign != 0 ) { BigInt *copy = inOtherInt->copy(); // flip sign copy->mSign = -( copy->mSign ); return copy; } else if( isEqualTo( inOtherInt ) ) { return getZero(); } else if( inOtherInt->mSign == -1 ) { // flip sign and add BigInt *copy = inOtherInt->copy(); copy->mSign = 1; BigInt *result = add( copy ); delete copy; return result; } else if( mSign == -1 ) { // flip our sign and add BigInt *copy = this->copy(); copy->mSign = 1; BigInt *result = inOtherInt->add( copy ); delete copy; // flip sign of result result->mSign = -1; return result; } else if( isLessThan( inOtherInt ) ) { // trying to subtract a larger number // flip subtraction order, then flip sign of result BigInt *result = inOtherInt->subtract( this ); result->mSign = -( result->mSign ); return result; } else { // we're subtracting a smaller positive number from // a larger positive number int maxLength = mNumBytes; if( maxLength < inOtherInt->mNumBytes ) { maxLength = inOtherInt->mNumBytes; } // result cannot be longer than the larger number unsigned char *result = new unsigned char[ maxLength ]; // flip to little-endian order to make subtracting easier BigInt *intA = this->flipByteOrder(); BigInt *intB = inOtherInt->flipByteOrder(); int borrow = 0; for( int i=0; imNumBytes ) { byteA = intA->mBytes[i]; } if( i < intB->mNumBytes ) { byteB = intB->mBytes[i]; } int diff = byteA - byteB - borrow; // compute next borrow borrow = 0; while( diff < 0 ) { borrow++; diff += 256; } result[i] = (unsigned char)diff; } BigInt *resultInt; if( borrow == 0 ) { // skip any trailing 0 bytes int bytesToSkip = 0; int index = maxLength - 1; while( index >= 0 && result[index] == 0 ) { bytesToSkip ++; index--; } // result array will be copied skipping borrow byte // and skipping any trailing 0 bytes resultInt = new BigInt( true, maxLength - bytesToSkip, result ); } else { printf( "Error: final borrow not zero: %d\n", borrow ); resultInt = getZero(); } BigInt *flippedResult = resultInt->flipByteOrder(); delete intA; delete intB; delete resultInt; delete [] result; return flippedResult; } } char BigInt::isLessThan( BigInt *inOtherInt ) { if( mSign > inOtherInt->mSign ) { return false; } else if( mSign < inOtherInt->mSign ) { return true; } else { // signs are equal if( mSign == 0 ) { return false; } else if( mSign == -1 && mNumBytes > inOtherInt->mNumBytes ) { return true; } else if( mSign == 1 && mNumBytes > inOtherInt->mNumBytes ) { return false; } else if( mSign == 1 && mNumBytes < inOtherInt->mNumBytes ) { return true; } else if( mSign == -1 && mNumBytes < inOtherInt->mNumBytes ) { return false; } else if( isEqualTo( inOtherInt ) ) { return false; } else { // numbers are the same length but are not equal // start with high-order bytes for( int i=0; i inOtherInt->mBytes[i] ) { if( mSign == 1 ) { return false; } else { return true; } } else if ( mBytes[i] < inOtherInt->mBytes[i] ) { if( mSign == 1 ) { return true; } else { return false; } } } // if we made it here, the numbers are equal... // but we tested for equality above: must be an error printf( "Error: equality test in isLessThan failed\n" ); return false; } } } char BigInt::isEqualTo( BigInt *inOtherInt ) { if( mSign != inOtherInt->mSign ) { return false; } else if( mNumBytes != inOtherInt->mNumBytes ) { return false; } else { // same length, same sign for( int i=0; imBytes[i] ) { // mismatch found return false; } } // no mismatch found return true; } } BigInt *BigInt::copy() { return new BigInt( mSign, mNumBytes, mBytes ); } BigInt *BigInt::getZero() { unsigned char bytes[0]; return new BigInt( 0, 0, bytes ); } /* THIS DOES NOT WORK! char *BigInt::convertToDecimalString() { char *tempString = new char[4]; char *resultString = new char[ mNumBytes * 3 + 1 ]; int stringIndex = 0; for( int i=0; i> 4 ); int lowBits = 0xF & ( currentByte ); resultHexString[ hexStringIndex ] = fourBitIntToHex( highBits ); hexStringIndex++; resultHexString[ hexStringIndex ] = fourBitIntToHex( lowBits ); hexStringIndex++; } resultHexString[ hexStringIndex ] = '\0'; return resultHexString; } } int BigInt::convertToInt() { int result = 0; int baseFactor = 1; for( int i=mNumBytes-1; i>=mNumBytes-4; i-- ) { if( i >=0 ) { result += mBytes[i] * baseFactor; } baseFactor *= 256; } return mSign * result; } BigInt *BigInt::flipByteOrder() { BigInt *returnInt = copy(); unsigned char *newBytes = returnInt->mBytes; int newIndex = mNumBytes - 1; for( int i=0; i int main() { unsigned char intA[] = { 100, 200, 99, 23, 89, 100, 233 }; unsigned char intB[] = { 10, 78, 243, 9, 0 }; BigInt *bigIntA = new BigInt( 1, 7, intA ); BigInt *bigIntB = new BigInt( -1, 5, intB ); char *hexA = bigIntA->convertToHexString(); char *hexB = bigIntB->convertToHexString(); printf( "A = %s\n", hexA ); printf( "B = %s\n", hexB ); BigInt *sum = bigIntA->subtract( bigIntB ); char *hexSum = sum->convertToHexString(); printf( "Sum = %s\n", hexSum ); delete [] hexA; delete [] hexB; delete [] hexSum; delete bigIntA; delete bigIntB; delete sum; int c = 0x58B11F; BigInt *intC = new BigInt( c ); char *hexC = intC->convertToHexString(); printf( "C = %s\n", hexC ); int extractedC = intC->convertToInt(); if( extractedC == c ) { printf( "equal\n" ); } else { printf( "not equal\n" ); } delete [] hexC; delete intC; int limit = 300; printf( "Testing pair operations for all pairs in -%d..%d ...\n", limit, limit ); char failed = false; for( int i=-limit; iadd( intJ ); BigInt *intDiff = intI->subtract( intJ ); int sum = i + j; int diff = i - j; if( sum != intSum->convertToInt() ) { printf( "sum test failed for %d, %d\n", i, j ); printf( " real sum = %d, computed sum = %d\n", sum, intSum->convertToInt() ); failed = true; } if( diff != intDiff->convertToInt() ) { printf( "diff test failed for %d, %d\n", i, j ); printf( " real diff = %d, computed diff = %d\n", diff, intDiff->convertToInt() ); failed = true; } if( intI->isLessThan( intJ ) && ( i >= j ) ) { printf( "first less than test failed for %d, %d\n", i, j ); failed = true; } if( intJ->isLessThan( intI ) && ( j >= i ) ) { printf( "second less than test failed for %d, %d\n", i, j ); failed = true; } if( intI->isEqualTo( intJ ) && ( i != j ) ) { printf( "equality test failed for %d, %d\n", i, j ); failed = true; } delete intSum; delete intDiff; delete intJ; } delete intI; } if( !failed ) { printf( "test passed\n" ); } return 0; } between-6+dfsg1.orig/minorGems/common.h0000640000175000017500000000033711435543333016651 0ustar pabspabs/* * Modification History * * 2002-October-18 Jason Rohrer * Created. */ #ifndef MINOR_GEMS_COMMON_INCLUDED #define MINOR_GEMS_COMMON_INCLUDED #include "minorGems/util/development/memory/debugMemory.h" #endif between-6+dfsg1.orig/minorGems/ui/0000750000175000017500000000000011435543337015625 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/ui/event/0000750000175000017500000000000011435543337016746 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/ui/event/ActionListener.h0000640000175000017500000000132311435543337022042 0ustar pabspabs/* * Modification History * * 2001-September-15 Jason Rohrer * Created. * * 2006-July-3 Jason Rohrer * Fixed warnings. */ #ifndef ACTION_LISTENER_INCLUDED #define ACTION_LISTENER_INCLUDED #include "minorGems/ui/GUIComponent.h" /** * An interface for a class that can handle a GUI action. * * @author Jason Rohrer */ class ActionListener { public: virtual ~ActionListener(); /** * Tells this class that an action has been performed. * * @param inTarget the GUI component on which the action * is being performed. */ virtual void actionPerformed( GUIComponent *inTarget ) = 0; }; inline ActionListener::~ActionListener() { } #endif between-6+dfsg1.orig/minorGems/ui/event/ActionListenerList.h0000640000175000017500000000475711435543337022714 0ustar pabspabs/* * Modification History * * 2001-September-15 Jason Rohrer * Created. * * 2001-September-17 Jason Rohrer * Fixed a missing include. * * 2006-July-3 Jason Rohrer * Fixed warnings. * * 2009-December-22 Jason Rohrer * New SimpleVector delete call. * * 2010-May-19 Jason Rohrer * Added call to check if a listener is on the list. */ #ifndef ACTION_LISTENER_LIST_INCLUDED #define ACTION_LISTENER_LIST_INCLUDED #include "ActionListener.h" #include "minorGems/ui/GUIComponent.h" #include "minorGems/util/SimpleVector.h" /** * A utility class to be subclassed by classes needing * to handle a list of action listeners. * * @author Jason Rohrer */ class ActionListenerList : protected SimpleVector { public: virtual ~ActionListenerList(); /** * Adds an action listener. * * @param inListener the listener to add. Must * be destroyed by caller after this class has been destroyed. */ virtual void addActionListener( ActionListener *inListener ); /** * Removes an action listener. * * @param inListener the listener to remove. Must * be destroyed by caller. */ virtual void removeActionListener( ActionListener *inListener ); /** * Checks if action listener added * * @param inListener the listener to look for. Must * be destroyed by caller. * * @return true iff listener is on the list */ virtual char isListening( ActionListener *inListener ); /** * Tells all registered listeners that an action has been * performed. * * @param inTarget the GUI component on which the action * is being performed. */ virtual void fireActionPerformed( GUIComponent *inTarget ); }; inline ActionListenerList::~ActionListenerList() { } inline void ActionListenerList::addActionListener( ActionListener *inListener ) { push_back( inListener ); } inline void ActionListenerList::removeActionListener( ActionListener *inListener ) { deleteElementEqualTo( inListener ); } inline char ActionListenerList::isListening( ActionListener *inListener ) { int index = getElementIndex( inListener ); if( index == -1 ) { return false; } else { return true; } } inline void ActionListenerList::fireActionPerformed( GUIComponent *inTarget ) { for( int i=0; iactionPerformed( inTarget ); } } #endif between-6+dfsg1.orig/minorGems/ui/GUIComponent.h0000640000175000017500000000060011435543337020302 0ustar pabspabs/* * Modification History * * 2001-September-15 Jason Rohrer * Created. */ #ifndef GUI_COMPONENT_INCLUDED #define GUI_COMPONENT_INCLUDED #include "minorGems/ui/GUIComponent.h" /** * An generic superclass for all gui components. * Allows for easy event source determination during event passing. * * @author Jason Rohrer */ class GUIComponent { }; #endif between-6+dfsg1.orig/minorGems/ui/Keyboard.h0000640000175000017500000000316111435543337017540 0ustar pabspabs/* * Modification History * * 2000-December-7 Jason Rohrer * Created. * * 2000-December-8 Jason Rohrer * Changed so that key state functions take a string instead of * an integer vkey code. * * 2006-June-26 Jason Rohrer * Added function to get events that are waiting in the queue. */ #ifndef KEYBOARD_INCLUDED #define KEYBOARD_INCLUDED /** * Interface for accessing keyboard input. * * Note: * Certain implementations may require a ScreenGraphics object to * be constructed before accessing the keyboard (i.e., to give the * keyboard input a context). */ class Keyboard { public: /* * Key descriptions: * * For the standard ascii characters, pass in the string containing * the lower case character, for example, "a" for the character A. * * For other keys, the descriptors have not been defined yet. */ /** * Gets whether a key is down. * * @param inKeyDescription string describing the queried key. * * @return true if key represented by given key code is down. */ //char getKeyDown( int vKeyCode ); char getKeyDown( const char *inKeyDescription ); /** * Gets whether a key is up. * * @param inKeyDescription string describing the queried key. * * @return true if key represented by given key code is up. */ //char getKeyUp( int vKeyCode ); char getKeyUp( const char *inKeyDescription ); /** * Gets the next keyboard event. * * @return the ASCII encoding of the pressed key, or -1 if no * keyboard events are waiting. */ int getKeyPressedEvent(); }; #endif between-6+dfsg1.orig/minorGems/ui/ProgressBar.h0000640000175000017500000000257011435543337020234 0ustar pabspabs// Jason Rohrer // ProgressBar.h /** * * ProgressBar Gui element * * * Created 11-6-99 * Mods: * Jason Rohrer 11-8-99 Changed to use GraphicBuffer object as screen buffer * */ #ifndef PROGRESS_BAR_INCLUDED #define PROGRESS_BAR_INCLUDED #include "Color.h" #include "GraphicBuffer.h" class ProgressBar { public: // construct a progress bar in a specific location with // specific border and maximum colors ProgressBar( int x, int y, int w, int h, Color bordC, Color hC, Color tipC ); ~ProgressBar(); void setProgress( float fractionFull ); // draw progress bar into a graphic buffer void draw( GraphicBuffer &buff ); // erase progress bar from buffer void erase( GraphicBuffer &buff, Color &bgColor ); private: unsigned long *imageMap; int startX; int startY; int high; int wide; int barHigh; // width and heigth of area inside borders int barWide; int *mapYOffset; Color borderC; // color of border Color highC; // color of progress bar max Color barTipC; static const int borderWide = 2; float lastProgress; // fraction of last progress }; inline void ProgressBar::draw( GraphicBuffer &buff ) { buff.drawImage(imageMap, mapYOffset, startX, startY, wide, high); } inline void ProgressBar::erase( GraphicBuffer &buff, Color &bgColor ) { buff.eraseImage(startX, startY, wide, high, bgColor); } #endifbetween-6+dfsg1.orig/minorGems/ui/linux/0000750000175000017500000000000011435543337016764 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/ui/linux/MouseLinux.cpp0000640000175000017500000000270611435543337021606 0ustar pabspabs/* * Modification History * * 2000-November-28 Jason Rohrer * Created. * * 2001-May-2 Jason Rohrer * Changed to use more standard SDL include location. */ #include "minorGems/ui/Mouse.h" #include /** * Note: Linux implementation: * Requires that a ScreenGraphics be constructed before accessing the mouse. */ void Mouse::getLocation( int *outX, int *outY ) { SDL_PumpEvents(); SDL_GetMouseState( outX, outY ); /* SDL_PumpEvents( void ); int numEventsToGet = 99; SDL_Event *events = new SDL_Event[numEventsToGet]; // get events from the queue int numEventsRetrieved = SDL_PeepEvents( events, numEventsToGet, SDL_GETEVENT, SDL_MOUSEMOTIONMASK ); // for mouse motion, we only care about the last event SDL_Event lastEvent = events[ numEventsRetrieved - 1 ]; delete [] events; */ } char Mouse::isButtonDown( int inButtonNumber ) { SDL_PumpEvents(); int x, y; Uint8 buttonState = SDL_GetMouseState( &x, &y ); if( inButtonNumber == 0 ) { return( buttonState & SDL_BUTTON_LMASK ); } if( mNumButtons >=3 ) { // if we care about 3 buttons, then count the middle button // as button 1 if( inButtonNumber == 1 ) { return( buttonState & SDL_BUTTON_MMASK ); } if( inButtonNumber == 2 ) { return( buttonState & SDL_BUTTON_RMASK ); } } else { // we care about 2 or fewer buttons if( inButtonNumber == 1 ) { return( buttonState & SDL_BUTTON_RMASK ); } } return false; } between-6+dfsg1.orig/minorGems/ui/linux/KeyboardLinux.cpp0000640000175000017500000000644611435543337022263 0ustar pabspabs/* * Modification History * * 2000-December-7 Jason Rohrer * Created. * * 2000-December-8 Jason Rohrer * Changed so that key state functions take a string instead of * an integer vkey code. * * 2001-May-2 Jason Rohrer * Changed to use more standard SDL include location. * * 2006-June-26 Jason Rohrer * Added function to get events that are waiting in the queue. */ #include "minorGems/ui/Keyboard.h" #include #include /** * Note: Linux implementation: * Requires that a ScreenGraphics be constructed before accessing the keyboard. */ // prototypes: /** * Maps an ascii string description of a key, such as "a", to an SDL keycode. * * @param inKeyDescription an ascii description of a key. * * @return the SDL keycode. */ int getKeyCode( const char *inKeyDescription ); /** * Maps a keycode to an ascii character. * * @param inSDLKeycode the keycode. * * @return the ascii character, or -1 if the keycode is not mappable to ascii. */ int getKeyASCII( int inSDLKeycode ); #define M_KEY SDLK_m #define N_KEY SDLK_n #define S_KEY SDLK_s #define Q_KEY SDLK_q #define L_KEY SDLK_l #define R_KEY SDLK_r #define T_KEY SDLK_t //char Keyboard::getKeyDown( int vKeyCode ) { char Keyboard::getKeyDown( const char *inKeyDescription ) { SDL_PumpEvents(); Uint8 *keys; keys = SDL_GetKeyState( NULL ); return keys[ getKeyCode( inKeyDescription ) ] == SDL_PRESSED; } //char Keyboard::getKeyUp( int vKeyCode ) { char Keyboard::getKeyUp( const char *inKeyDescription ) { SDL_PumpEvents(); Uint8 *keys; keys = SDL_GetKeyState( NULL ); return keys[ getKeyCode( inKeyDescription ) ] == SDL_RELEASED; } int Keyboard::getKeyPressedEvent() { SDL_Event event; if( SDL_PollEvent( &event ) ) { switch( event.type ) { case SDL_KEYDOWN: return getKeyASCII( event.key.keysym.sym ); break; } } else { return -1; } } int getKeyCode( const char *inKeyDescription ) { // note that strcmp functions return 0 if strings match if( !strcasecmp( inKeyDescription, "m" ) ) { return SDLK_m; } else if( !strcasecmp( inKeyDescription, "n" ) ) { return SDLK_n; } else if( !strcasecmp( inKeyDescription, "s" ) ) { return SDLK_s; } else if( !strcasecmp( inKeyDescription, "q" ) ) { return SDLK_q; } else if( !strcasecmp( inKeyDescription, "l" ) ) { return SDLK_l; } else if( !strcasecmp( inKeyDescription, "r" ) ) { return SDLK_r; } else if( !strcasecmp( inKeyDescription, "t" ) ) { return SDLK_t; } } int getKeyASCII( int inSDLKeycode ) { switch( inSDLKeycode ) { case SDLK_m: return 'm'; break; case SDLK_n: return 'n'; break; case SDLK_s: return 's'; break; case SDLK_q: return 'a'; break; case SDLK_l: return 'l'; break; case SDLK_r: return 'r'; break; case SDLK_t: return 't'; break; default: return -1; break; } } /* #define M_KEY SDLK_m #define N_KEY SDLK_n #define S_KEY SDLK_s #define Q_KEY SDLK_q #define L_KEY SDLK_l #define R_KEY SDLK_r #define T_KEY SDLK_t */ between-6+dfsg1.orig/minorGems/ui/SetMouseMac.cpp0000640000175000017500000000140111435543337020513 0ustar pabspabs// Jason Rohrer // SetMouseMac.cpp /** * * implementation of SetMouse on Mac * This uses a hack that may not be supported in later OSs (e.g., OSX) * * Created 1-14-2000 * Mods: */ #include #include "SetMouse.h" void SetMouse (int x, int y) { Point base; // This routine donated to MacMAME by John Stiles // Picked up for RadiosGL from the Mac GLQuake site Point *RawMouse = (Point*) 0x82C; Point *MTemp = (Point*) 0x828; Ptr CrsrNew = (Ptr) 0x8CE; Ptr CrsrCouple = (Ptr) 0x8CF; base.v = y; base.h = x; LocalToGlobal(&base); *RawMouse = base; *MTemp = base; *CrsrNew = *CrsrCouple; } // do nothing, these are needed in windows only void CaptureMouse() { } void ReleaseMouse() { }between-6+dfsg1.orig/minorGems/ui/ProgressBar.cpp0000640000175000017500000000500211435543337020560 0ustar pabspabs// Jason Rohrer // ProgressBar.cpp /** * * ProgressBar Gui element implementation * * * Created 11-6-99 * Mods: * Jason Rohrer 11-8-99 Changed to use GraphicBuffer object as screen buffer * */ #include "ProgressBar.h" ProgressBar::ProgressBar(int x, int y, int w, int h, Color bordC, Color hC, Color tipC) { startX = x; startY = y; wide = w; high = h; barWide = wide - 2*borderWide; barHigh = high - 2*borderWide; borderC = bordC; highC = hC; barTipC = tipC; imageMap = new unsigned long[high * wide]; mapYOffset = new int[high]; // precalc y offsets into 2d image map for( int y=0; yhigh-borderWide-1 || x>wide-borderWide-1 ) { imageMap[ yContrib + x ] = borderC.composite; // border } else { imageMap[ yContrib + x ] = 0xFF000000; // black inside } } } lastProgress = 0; } ProgressBar::~ProgressBar() { delete [] imageMap; delete [] mapYOffset; } void ProgressBar::setProgress(float fractionFull) { if( fractionFull < 0) fractionFull = 0; if( fractionFull > 1) fractionFull = 1; if( fractionFull < lastProgress ) { // decreasing proress, erase part of bar int deleteXStart = (int)((fractionFull) * barWide + borderWide); int deleteXEnd = (int)((lastProgress) * barWide + borderWide); for( int y=borderWide; y lastProgress) { //progress has increased int addXStart = (int)((lastProgress) * barWide + borderWide); int addXEnd = (int)((fractionFull) * barWide + borderWide); float weight = lastProgress; float deltaWeight = (fractionFull - lastProgress) / (addXEnd - addXStart); for( int x=addXStart; x #include "SetMouse.h" char captured = false; void SetMouse( int x, int y ) { POINT p; p.x = x; p.y = y; HWND window = GetActiveWindow(); ClientToScreen( window, &p ); SetCursorPos( p.x, p.y ); //SetCursorPos( x, y ); } // send all mouse movements to our window, even those outside the border void CaptureMouse() { HWND window = GetActiveWindow(); SetCapture( window ); } void ReleaseMouse() { ReleaseCapture(); }between-6+dfsg1.orig/minorGems/ui/Mouse.h0000640000175000017500000000327411435543337017075 0ustar pabspabs/* * Modification History * * 2000-November-28 Jason Rohrer * Created. */ #ifndef MOUSE_INCLUDED #define MOUSE_INCLUDED /** * Interface for accessing mouse input. * * Note: * Certain implementations may require a ScreenGraphics object to * be constructed before accessing the mouse (i.e., to give the * mouse coordinates a context). */ class Mouse { public: /** * Constructs a Mouse. * * @param inNumButtons the number of buttons on the mouse that should * be monitored. Default = 1. */ Mouse( int inNumButtons ); ~Mouse(); /** * Gets the location of the mouse. * * @param outX pointer to location where x component will be returned. * @param outY pointer to location where y component will be returned. */ void getLocation( int *outX, int *outY ); /** * Gets whether the main mouse button is down. * * @return true if the main mouse button is down. */ char isButtonDown(); /** * Gets whether a specified mouse button is down. * * @param inButtonNumber the number of the button to check for * (0 is the main mouse button). * * @return true if the specified mouse button is down. */ char isButtonDown( int inButtonNumber ); private: int mXLocation; int mYLocation; int mNumButtons; // array of booleans that represent the current // (or last known) state of each button char *mButtonDown; }; inline Mouse::Mouse( int inNumButtons = 1 ) : mNumButtons( inNumButtons ), mButtonDown( new char[inNumButtons] ) { } inline Mouse::~Mouse() { delete [] mButtonDown; } inline char Mouse::isButtonDown() { return isButtonDown( 0 ); } #endif between-6+dfsg1.orig/minorGems/ui/Plot.h0000640000175000017500000000262511435543337016722 0ustar pabspabs// Jason Rohrer // Plot.h /** * * Scrolling Plot Gui element * * * Created 11-7-99 * Mods: * Jason Rohrer 11-8-99 Changed to use GraphicBuffer object as screen buffer * */ #ifndef PLOT_INCLUDED #define PLOT_INCLUDED #include #include "Color.h" #include "GraphicBuffer.h" class Plot { public: // construct a plot in a specific location with // specific border, background, and line colors Plot( int x, int y, int w, int h, Color bordC, Color bC, Color lnC ); ~Plot(); // add a point to the right of plot, cause plot to scroll left void addPoint( float p ); // draw plot into a graphic buffer void draw( GraphicBuffer &buff ); // erase plot from buffer void erase( GraphicBuffer &buff, Color &bgColor ); private: unsigned long *imageMap; int startX; int startY; int high; int wide; int innerHigh; // width and heigth of area inside borders int innerWide; int *mapYOffset; Color borderC; // color of border Color bgC; // color of progress bar max Color lineC; // color of plot line static const int borderWide = 2; float *plotVals; // values of plot line }; inline void Plot::draw( GraphicBuffer &buff ) { buff.drawImage(imageMap, mapYOffset, startX, startY, wide, high); } inline void Plot::erase( GraphicBuffer &buff, Color &bgColor ) { buff.eraseImage(startX, startY, wide, high, bgColor); } #endifbetween-6+dfsg1.orig/minorGems/ui/SetMouse.h0000640000175000017500000000042411435543337017543 0ustar pabspabs// Jason Rohrer // SetMouse.h /** * * Interface for force-setting mouse cursor position * * Created 1-14-2000 * Mods: * Jason Rohrer 1-18-2000 Added capture and release mouse functions to help Win32 */ void SetMouse( int x, int y); void CaptureMouse(); void ReleaseMouse();between-6+dfsg1.orig/minorGems/ui/Plot.cpp0000640000175000017500000000456111435543337017256 0ustar pabspabs// Jason Rohrer // Plot.cpp /** * * Scrolling Plot Gui element implementation * * * Created 11-7-99 * Mods: * Jason Rohrer 11-8-99 Changed to use GraphicBuffer object as screen buffer * */ #include "Plot.h" Plot::Plot( int x, int y, int w, int h, Color bordC, Color bC, Color lnC ) { startX = x; startY = y; wide = w; high = h; innerWide = wide - 2*borderWide; innerHigh = high - 2*borderWide; borderC = bordC; bgC = bC; lineC = lnC; imageMap = new unsigned long[high * wide]; mapYOffset = new int[high]; // precalc y offsets into 2d image map for( int y=0; yhigh-borderWide-1 || x>wide-borderWide-1 ) { imageMap[ yContrib + x ] = borderC.composite; // border } else { imageMap[ yContrib + x ] = bgC.composite; // background } } } plotVals = new float[innerWide]; for( int i=0; i 0) { invLargest = 1/largest; } // fill plot with bg color for( int y=borderWide; y innerHigh + borderWide ) y = innerHigh + borderWide -1; if( y < borderWide ) y = borderWide; imageMap[ mapYOffset[y] + x ] = lineC.composite; // line } /* for( int x=0; x> ${MINOR_GEMS_DEPENDENCY_FILE}.temp cat ${MINOR_GEMS_DEPENDENCY_FILE}.temp | ${MINOR_GEMS_SED_FIX_COMMAND_A} | ${MINOR_GEMS_SED_FIX_COMMAND_B} >> ${MINOR_GEMS_DEPENDENCY_FILE} rm -f ${MINOR_GEMS_DEPENDENCY_FILE}.temp include ${MINOR_GEMS_DEPENDENCY_FILE} between-6+dfsg1.orig/minorGems/io/0000750000175000017500000000000011435543334015614 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/io/Serializable.h0000640000175000017500000000345611435543334020404 0ustar pabspabs/* * Modification History * * 2001-January-10 Jason Rohrer * Created. * Added untility functions for converting integers to and from byte arrays. * * 2001-January-15 Jason Rohrer * Made utility functions static. * Fixed a major bug in the longToBytes function. * * 2001-February-3 Jason Rohrer * Removed the long io functions, which are now contained in the * input- and outputStream classes. * * 2005-November-21 Jason Rohrer * Fixed a warning by adding a virtual destructor. */ #include "minorGems/common.h" #ifndef SERIALIZABLE_CLASS_INCLUDED #define SERIALIZABLE_CLASS_INCLUDED #include "InputStream.h" #include "OutputStream.h" /** * Interface for an object that can be serialized to and deserialized * from a stream. * * Note that the deserialize function is meant to be called from an already * constructed object (to set object parameters using data read from the * stream), and is not a method of obtaining an object. * * All multi-byte data members should be encoded in using a big endian format. * * @author Jason Rohrer */ class Serializable { public: /** * Writes this object out to a stream. * * @param inOutputStream the stream to write to. * * @return the number of bytes written successfully, * or -1 for a stream error. */ virtual int serialize( OutputStream *inOutputStream ) = 0; /** * Reads this object in from a stream. * * @param inInputStream the stream to read from. * * @return the number of bytes read successfully, * or -1 for a stream error. */ virtual int deserialize( InputStream *inInputStream ) = 0; virtual ~Serializable(); }; inline Serializable::~Serializable() { // does nothing // exists to ensure that subclass destructors are called } #endif between-6+dfsg1.orig/minorGems/io/file/0000750000175000017500000000000011435543334016533 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/io/file/unix/0000750000175000017500000000000011435543334017516 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/io/file/unix/DirectoryUnix.cpp0000640000175000017500000000141211435543334023031 0ustar pabspabs/* * Modification History * * 2003-January-23 Jason Rohrer * Created. * * 2003-November-10 Jason Rohrer * Added makeDirectory function. */ #include "minorGems/io/file/Directory.h" #include char Directory::removeDirectory( File *inFile ) { char *fileName = inFile->getFullFileName(); int result = rmdir( fileName ); delete [] fileName; if( result == 0 ) { return true; } else { return false; } } char Directory::makeDirectory( File *inFile ) { char *stringName = inFile->getFullFileName(); int result = mkdir( stringName, 0xFFFF ); delete [] stringName; if( 0 == result ) { return true; } else { return false; } } between-6+dfsg1.orig/minorGems/io/file/FileInputStream.h0000640000175000017500000000740211435543334021763 0ustar pabspabs/* * Modification History * * 2001-February-11 Jason Rohrer * Created. * * 2001-April-12 Jason Rohrer * Changed so that File is not destroyed when this stream is destroyed. * * 2001-April-29 Jason Rohrer * Fixed a bug in the use of fread * (num elements and element size swapped). * Fixed a memory leak in the error message handling. * * 2006-November-23 Jason Rohrer * Fixed a memory leak in error message handling. * * 2010-April-22 Jason Rohrer * Added support for text mode. */ #include "minorGems/common.h" #ifndef FILE_INPUT_STREAM_CLASS_INCLUDED #define FILE_INPUT_STREAM_CLASS_INCLUDED #include "minorGems/io/InputStream.h" #include "File.h" #include /** * File implementation of an InputStream. * * @author Jason Rohrer */ class FileInputStream : public InputStream { public: /** * Constructs an input stream. * * @param inFile the file to open for reading. * If the file does not exist, all calls to read will fail. * inFile is NOT destroyed when this class is destroyed. * @param inTextMode true to open the file as text, false as binary. * Defaults to false. */ FileInputStream( File *inFile, char inTextMode = false ); /** * Destroys this stream and closes the file. */ ~FileInputStream(); /** * Gets the file attached to this stream. * * @return the file used by this stream. * Should not be modified or destroyed by caller until after * this class is destroyed. */ File *getFile(); // implementst InputStream interface virtual long read( unsigned char *inBuffer, long inNumBytes ); private: File *mFile; FILE *mUnderlyingFile; }; inline FileInputStream::FileInputStream( File *inFile, char inTextMode ) : mFile( inFile ) { int fileNameLength; char *fileName = mFile->getFullFileName( &fileNameLength ); if( inTextMode ) { mUnderlyingFile = fopen( fileName, "r" ); } else { mUnderlyingFile = fopen( fileName, "rb" ); } if( mUnderlyingFile == NULL ) { // file open failed. char *stringBuffer = new char[ fileNameLength + 50 ]; sprintf( stringBuffer, "Opening file %s failed.", fileName ); setNewLastError( stringBuffer ); } delete [] fileName; } inline FileInputStream::~FileInputStream() { if( mUnderlyingFile != NULL ) { fclose( mUnderlyingFile ); } } inline File *FileInputStream::getFile() { return mFile; } inline long FileInputStream::read( unsigned char *inBuffer, long inNumBytes ) { if( mUnderlyingFile != NULL ) { long numRead = fread( inBuffer, 1, inNumBytes, mUnderlyingFile ); if( numRead < inNumBytes ) { int fileNameLength; char *fileName = mFile->getFullFileName( &fileNameLength ); if( feof( mUnderlyingFile ) ) { // we reached the end of the file. char *stringBuffer = new char[ fileNameLength + 50 ]; sprintf( stringBuffer, "Reached end of file %s on read.", fileName ); setNewLastError( stringBuffer ); delete [] fileName; } else { // some other kind of error occured char *stringBuffer = new char[ fileNameLength + 50 ]; sprintf( stringBuffer, "Reading from file %s failed.", fileName ); setNewLastError( stringBuffer ); delete [] fileName; if( numRead == 0 ) { // a complete read failure return -1; } } } return numRead; } else { // file was not opened properly int fileNameLength; char *fileName = mFile->getFullFileName( &fileNameLength ); char *stringBuffer = new char[ fileNameLength + 50 ]; sprintf( stringBuffer, "File %s was not opened properly before reading.", fileName ); delete [] fileName; setNewLastError( stringBuffer ); return -1; } } #endif between-6+dfsg1.orig/minorGems/io/file/FileOutputStream.h0000640000175000017500000000667211435543334022174 0ustar pabspabs/* * Modification History * * 2001-February-11 Jason Rohrer * Created. * * 2001-April-12 Jason Rohrer * Changed so that File is not destroyed when this stream is destroyed. * * 2001-April-29 Jason Rohrer * Fixed a bug in the use of fwrite * (num elements and element size swapped). * Fixed a memory leak in the error message handling. * * 2006-August-22 Jason Rohrer * Fixed include order bug. * * 2010-April-6 Jason Rohrer * Fixed memory leak. */ #include "minorGems/common.h" #include "File.h" #ifndef FILE_OUTPUT_STREAM_CLASS_INCLUDED #define FILE_OUTPUT_STREAM_CLASS_INCLUDED #include "minorGems/io/OutputStream.h" #include /** * File implementation of an OutputStream. * * @author Jason Rohrer */ class FileOutputStream : public OutputStream { public: /** * Constructs an output stream. * * @param inFile the file to open for writing. * If the file does not exist, it will be created. * inFile is NOT destroyed when this class is destroyed. * @param inAppend set to true to append to file. If * file does not exist, file is still created. Defaults * to false. */ FileOutputStream( File *inFile, char inAppend = false ); /** * Destroys this stream and closes the file. */ ~FileOutputStream(); /** * Gets the file attached to this stream. * * @return the file used by this stream. * Should not be modified or destroyed by caller until after * this class is destroyed. */ File *getFile(); // implementst OutputStream interface virtual long write( unsigned char *inBuffer, long inNumBytes ); private: File *mFile; FILE *mUnderlyingFile; }; inline FileOutputStream::FileOutputStream( File *inFile, char inAppend ) : mFile( inFile ) { int fileNameLength; char *fileName = mFile->getFullFileName( &fileNameLength ); if( inAppend ) { mUnderlyingFile = fopen( fileName, "ab" ); } else { mUnderlyingFile = fopen( fileName, "wb" ); } if( mUnderlyingFile == NULL ) { // file open failed. char *stringBuffer = new char[ fileNameLength + 50 ]; sprintf( stringBuffer, "Opening file %s failed.", fileName ); setNewLastError( stringBuffer ); } delete [] fileName; } inline FileOutputStream::~FileOutputStream() { if( mUnderlyingFile != NULL ) { fclose( mUnderlyingFile ); } } inline File *FileOutputStream::getFile() { return mFile; } inline long FileOutputStream::write( unsigned char *inBuffer, long inNumBytes ) { if( mUnderlyingFile != NULL ) { long numWritten = fwrite( inBuffer, 1, inNumBytes, mUnderlyingFile ); if( numWritten < inNumBytes ) { int fileNameLength; char *fileName = mFile->getFullFileName( &fileNameLength ); // some other kind of error occured char *stringBuffer = new char[ fileNameLength + 50 ]; sprintf( stringBuffer, "Writing to file %s failed.", fileName ); setNewLastError( stringBuffer ); delete [] fileName; if( numWritten == 0 ) { // a complete write failure return -1; } } return numWritten; } else { // file was not opened properly int fileNameLength; char *fileName = mFile->getFullFileName( &fileNameLength ); char *stringBuffer = new char[ fileNameLength + 50 ]; sprintf( stringBuffer, "File %s was not opened properly before writing.", fileName ); delete [] fileName; setNewLastError( stringBuffer ); return -1; } } #endif between-6+dfsg1.orig/minorGems/io/file/testPath.cpp0000640000175000017500000000112211435543334021030 0ustar pabspabs/* * Modification History * * 2002-August-1 Jason Rohrer * Created. */ #include "Path.h" #include int main() { char *pathString = "/test/this/thing"; printf( "using path string = %s\n", pathString ); printf( "Constructing path.\n" ); Path *path = new Path( pathString ); printf( "Extracting path string.\n" ); char *extractedPathString = path->getPathStringTerminated(); printf( "extracted path string = %s\n", extractedPathString ); delete [] extractedPathString; delete path; return 1; } between-6+dfsg1.orig/minorGems/io/file/File.h0000640000175000017500000005422311435543334017572 0ustar pabspabs/* * Modification History * * 2001-February-11 Jason Rohrer * Created. * * 2001-February-25 Jason Rohrer * Fixed file name bugs in length and existence functions. * * 2001-May-11 Jason Rohrer * Added a missing include. * * 2001-November-3 Jason Rohrer * Added a function for checking if a file is a directory. * Added a function for getting the child files of a directory. * Added a function for getting a pathless file name. * * 2001-November-13 Jason Rohrer * Made name length parameter optional in constructor. * Made return length parameter optional in name getting functions. * * 2001-November-17 Jason Rohrer * Added a functions for removing a file and for copying a file. * * 2002-March-11 Jason Rohrer * Added destruction comment to getFullFileName(). * * 2002-March-13 Jason Rohrer * Changed mName to be \0-terminated to fix interaction bugs with Path. * Fixed a missing delete. * Added a function for creating a directory. * * 2002-March-31 Jason Rohrer * Fixed some bad syntax. * * 2002-April-6 Jason Rohrer * Replaced use of strdup. * * 2002-April-8 Jason Rohrer * Fixed fopen bug. * * 2002-April-11 Jason Rohrer * Fixed a memory leak. * Fixed a casting error. * * 2002-June-28 Jason Rohrer * Added a function for copying a file class. * * 2002-August-3 Jason Rohrer * Added a function for getting the parent file. * * 2002-August-5 Jason Rohrer * Used an unused error variable. * * 2002-September-11 Jason Rohrer * Added return value to remove. * * 2003-January-27 Jason Rohrer * Added a function for reading file contents. * * 2003-February-3 Jason Rohrer * Added a function for writing a string to a file. * * 2003-March-13 Jason Rohrer * Added a function for getting a child file from a directory. * * 2003-June-2 Jason Rohrer * Fixed parent directory behavior when current file is root directory. * Fixed a bug in getting child files of root directory. * * 2003-November-6 Jason Rohrer * Added function for getting last modification time. * * 2003-November-10 Jason Rohrer * Changed to use platform-dependent makeDirectory function. * * 2004-January-4 Jason Rohrer * Added recursive child file functions. * * 2005-August-29 Jason Rohrer * Fixed an uninitialized variable warning. * * 2010-March-6 Jason Rohrer * Added versions of writeToFile readFileContents for binary data. * * 2010-April-23 Jason Rohrer * Fixed a string length bug when line ends are Windows. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ #include "minorGems/common.h" #ifndef FILE_CLASS_INCLUDED #define FILE_CLASS_INCLUDED #include #include #include #include #include "Path.h" #include "minorGems/util/SimpleVector.h" #include "minorGems/util/stringUtils.h" /** * File interface. Provides access to information about a * file. * * @author Jason Rohrer */ class File { public: /** * Constructs a file. * * @param inPath the path for this file. * Is destroyed when this class is destroyed. * Pass in NULL to specify * no path (the current working directory). * @param inName the name of the file to open. * Must be destroyed by caller if not const. * Copied internally. * @param inNameLength length of the name in chars, * or -1 to use the c-string length of inName * (assuming that inName is \0-terminated). * Defaults to -1. */ File( Path *inPath, const char *inName, int inNameLength = -1 ); ~File(); /** * Gets whether this file is a directory. * * @return true iff this file is a directory. */ char isDirectory(); /** * Makes a directory in the location of this file. * * Can only succeed if exists() is false. * * @return true iff directory creation succeeded. */ char makeDirectory(); /** * Gets the files contained in this file if it is a directory. * * @param outNumFiles pointer to where the number of * files will be returned. * * @return an array of files, or NULL if this * file is not a directory, is an empty directory, or doesn't exist. * Must be destroyed by caller if non-NULL. */ File **getChildFiles( int *outNumFiles ); /** * Gets the files contained in this file if it is a directory and * recursively in subdirectories of this file. * * @param inDepthLimit the maximum subdirectory depth to recurse into. * If inDepthLimit is 0, then only child files in this directory * will be returned. * @param outNumFiles pointer to where the number of * files will be returned. * * @return an array of files, or NULL if this * file is not a directory, is an empty directory (or a directory * containing empty subdirectories), or doesn't exist. * Must be destroyed by caller if non-NULL. */ File **getChildFilesRecursive( int inDepthLimit, int *outNumFiles ); /** * Gets a child of this directory. * * @param inChildFileName the name of the child file. * Must be destroyed by caller if non-const. * * @return the child file (even if it does not exist), or NULL if * this file is not a directory. * Must be destroyed by caller if non-NULL. */ File *getChildFile( const char *inChildFileName ); /** * Gets the parent directory of this file. * * @return the parent directory of this file. * Must be destroyed by caller. */ File *getParentDirectory(); /** * Gets the length of this file. * * @return the length of this file in bytes. Returns * 0 if the file does not exist. */ long getLength(); /** * Gets whether a file exists. * * @return true if the file exists. */ char exists(); /** * Gets the last modification time of this file. * * @return the modification time in seconds based on the * system clock. Returns 0 if the file does not exist. */ unsigned long getModificationTime(); /** * Removes this file from the disk, if it exists. * * @return true iff the remove succeeded, false if the removal * fails or the file does not exist. */ char remove(); /** * Copies this file object (does not copy the file described by * this object). * * @return a deep copy of this file object. */ File *copy(); /** * Copies the contents of this file into another file. * * @param inDestination the file to copy this file into. * If it exists, it will be overwritten. * If it does not exist, it will be created. * Must be destroyed by caller. * @param inBlockSize the block size to use when copying. * Defaults to blocks of 5000 bytes. */ void copy( File *inDestination, long inBlockSize = 5000 ); /** * Gets the full-path file name sufficient * to access this file from the current working * directory. * * @param outLength pointer to where the name length, in * characters, will be returned. Set to NULL to ignore * the output length. Defaults to NULL. * * @return the full path file name for this file, * in platform-specific form. Must be destroyed by caller. * The returned string is '\0' terminated, but this * extra character is not included in the length. * Must be destroyed by caller. */ char *getFullFileName( int *outLength = NULL ); /** * Gets the pathless name of this file. * * @param outLength pointer to where the name length, in * characters, will be returned. Set to NULL to ignore * the output length. Defaults to NULL. * * @return the name of this file. Must be destroyed by caller. */ char *getFileName( int *outLength = NULL ); /** * Reads the contents of this file. * * @return a \0-terminated string containing the file contents, * or NULL if reading the file into memory failed. * Must be destroyed by caller. */ char *readFileContents(); /** * Reads the contents of this file. * * @param outLength pointer to where the return array length should * be returned. * @param inTextMode true to open the file as text, false as binary. * Defaults to false. * * @return an array containing the binary file contents, * or NULL if reading the file into memory failed. * Must be destroyed by caller. */ unsigned char *readFileContents( int *outLength, char inTextMode = false ); /** * Writes a string to this file. * * @param inString the \0-terminated string to write. * Must be destroyed by caller if non-const. * * @return true if the file was written to successfully, or * false otherwise. */ char writeToFile( const char *inString ); /** * Writes a binary data to this file. * * @param inData the data to write. * Must be destroyed by caller if non-const. * @param inLength length of inData. * * @return true if the file was written to successfully, or * false otherwise. */ char writeToFile( unsigned char *inData, int inLength ); private: Path *mPath; char *mName; int mNameLength; /** * Gets the files contained in this file if it is a directory and * recursively in subdirectories of this file. * * @param inDepthLimit the maximum subdirectory depth to recurse into. * If inDepthLimit is 0, then only child files in this directory * will be returned. * @param inResultVector vector to add the discovered files to. * Must be destroyed by caller. */ void getChildFilesRecursive( int inDepthLimit, SimpleVector *inResultVector ); }; inline File::File( Path *inPath, const char *inName, int inNameLength ) : mPath( inPath ), mNameLength( inNameLength ) { if( inNameLength == -1 ) { inNameLength = strlen( inName ); mNameLength = inNameLength; } // copy name internally mName = stringDuplicate( inName ); } inline File::~File() { delete [] mName; if( mPath != NULL ) { delete mPath; } } inline long File::getLength() { struct stat fileInfo; // get full file name int length; char *stringName = getFullFileName( &length ); int statError = stat( stringName, &fileInfo ); delete [] stringName; if( statError == 0 ) { return fileInfo.st_size; } else { // file does not exist return 0; } } inline char File::isDirectory() { struct stat fileInfo; // get full file name int length; char *stringName = getFullFileName( &length ); int statError = stat( stringName, &fileInfo ); delete [] stringName; if( statError == -1 ) { return false; } else { return S_ISDIR( fileInfo.st_mode ); } } inline File **File::getChildFiles( int *outNumFiles ) { int length; char *stringName = getFullFileName( &length ); DIR *directory = opendir( stringName ); if( directory != NULL ) { SimpleVector< File* > *fileVector = new SimpleVector< File* >(); struct dirent *entry = readdir( directory ); if( entry == NULL ) { delete fileVector; closedir( directory ); delete [] stringName; *outNumFiles = 0; return NULL; } while( entry != NULL ) { // skip parentdir and thisdir files, if they occur if( strcmp( entry->d_name, "." ) && strcmp( entry->d_name, ".." ) ) { Path *newPath; if( mPath != NULL ) { newPath = mPath->append( mName ); } else { if( Path::isRoot( mName ) ) { // use name as a string path newPath = new Path( mName ); } else { char **folderPathArray = new char*[1]; folderPathArray[0] = mName; // a non-absolute path to this directory's contents int numSteps = 1; char absolute = false; newPath = new Path( folderPathArray, numSteps, absolute ); delete [] folderPathArray; } } // safe to pass d_name in directly because it is copied // internally by the constructor fileVector->push_back( new File( newPath, entry->d_name, strlen( entry->d_name ) ) ); } entry = readdir( directory ); } // now we have a vector full of this directory's files int vectorSize = fileVector->size(); *outNumFiles = vectorSize; if( vectorSize == 0 ) { delete fileVector; closedir( directory ); delete [] stringName; return NULL; } else { File **returnFiles = new File *[vectorSize]; for( int i=0; igetElement( i ) ); } delete fileVector; closedir( directory ); delete [] stringName; return returnFiles; } } else { delete [] stringName; *outNumFiles = 0; return NULL; } } inline File **File::getChildFilesRecursive( int inDepthLimit, int *outNumFiles ) { // create a vector for results SimpleVector *resultVector = new SimpleVector(); // call the recursive function getChildFilesRecursive( inDepthLimit, resultVector ); // extract results from vector File **resultArray = NULL; int numResults = resultVector->size(); if( numResults > 0 ) { resultArray = resultVector->getElementArray(); } delete resultVector; *outNumFiles = numResults; return resultArray; } inline void File::getChildFilesRecursive( int inDepthLimit, SimpleVector *inResultVector ) { // get our child files int numChildren; File **childFiles = getChildFiles( &numChildren ); if( childFiles != NULL ) { // for each child, add it to vector and // recurse into it if it is a directory for( int i=0; ipush_back( child ); if( child->isDirectory() ) { // skip recursion if we have hit our depth limit if( inDepthLimit > 0 ) { // recurse into this subdirectory child->getChildFilesRecursive( inDepthLimit - 1, inResultVector ); } } } delete [] childFiles; } } inline File *File::getChildFile( const char *inChildFileName ) { // make sure we are a directory if( !isDirectory() ) { return NULL; } // get a path to this directory Path *newPath; if( mPath != NULL ) { newPath = mPath->append( mName ); } else { char **folderPathArray = new char*[1]; folderPathArray[0] = mName; // a non-absolute path to this directory's contents int numSteps = 1; char absolute = false; newPath = new Path( folderPathArray, numSteps, absolute ); delete [] folderPathArray; } return new File( newPath, inChildFileName ); } inline File *File::getParentDirectory() { if( mPath != NULL ) { char *parentName; Path *parentPath; if( strcmp( mName, ".." ) == 0 ) { // already a parent dir reference // append one more parent dir reference with parentName below parentPath = mPath->append( ".." ); parentName = stringDuplicate( ".." ); } else { // not a parent dir reference, so we can truncate parentPath = mPath->truncate(); parentName = mPath->getLastStep(); } File *parentFile = new File( parentPath, parentName ); delete [] parentName; return parentFile; } else { if( Path::isRoot( mName ) ) { // we are already at the root return new File( NULL, mName ); } else { // append parent dir symbol to path char **parentPathSteps = new char*[1]; parentPathSteps[0] = mName; Path *parentPath = new Path( parentPathSteps, 1, false ); const char *parentName = ".."; File *parentFile = new File( parentPath, parentName ); delete [] parentPathSteps; return parentFile; } } } inline char File::exists() { struct stat fileInfo; // get full file name int length; char *stringName = getFullFileName( &length ); int statError = stat( stringName, &fileInfo ); delete [] stringName; if( statError == 0 ) { return true; } else { // file does not exist return false; } } inline unsigned long File::getModificationTime() { struct stat fileInfo; // get full file name int length; char *stringName = getFullFileName( &length ); int statError = stat( stringName, &fileInfo ); delete [] stringName; if( statError == 0 ) { return fileInfo.st_mtime; } else { // file does not exist return 0; } } inline char File::remove() { char returnVal = false; if( exists() ) { char *stringName = getFullFileName(); int error = ::remove( stringName ); if( error == 0 ) { returnVal = true; } delete [] stringName; } return returnVal; } inline File *File::copy() { Path *pathCopy = NULL; if( mPath != NULL ) { pathCopy = mPath->copy(); } return new File( pathCopy, mName ); } inline void File::copy( File *inDestination, long inBlockSize ) { char *thisFileName = getFullFileName(); char *destinationFileName = inDestination->getFullFileName(); FILE *thisFile = fopen( thisFileName, "rb" ); FILE *destinationFile = fopen( destinationFileName, "wb" ); long length = getLength(); long bytesCopied = 0; char *buffer = new char[ inBlockSize ]; while( bytesCopied < length ) { long bytesToCopy = inBlockSize; // end of file case if( length - bytesCopied < bytesToCopy ) { bytesToCopy = length - bytesCopied; } fread( buffer, 1, bytesToCopy, thisFile ); fwrite( buffer, 1, bytesToCopy, destinationFile ); bytesCopied += bytesToCopy; } fclose( thisFile ); fclose( destinationFile ); delete [] buffer; delete [] thisFileName; delete [] destinationFileName; } inline char *File::getFileName( int *outLength ) { char *returnName = stringDuplicate( mName ); if( outLength != NULL ) { *outLength = mNameLength; } return returnName; } inline char *File::getFullFileName( int *outLength ) { int length = mNameLength; int pathLength = 0; char *path = NULL; if( mPath != NULL ) { path = mPath->getPathString( &pathLength ); length += pathLength; } // extra character for '\0' termination char *returnString = new char[ length + 1 ]; if( path != NULL ) { memcpy( returnString, path, pathLength ); memcpy( &( returnString[pathLength] ), mName, mNameLength ); delete [] path; } else { // no path, so copy the name directly in memcpy( returnString, mName, mNameLength ); } // terminate the string returnString[ length ] = '\0'; if( outLength != NULL ) { *outLength = length; } return returnString; } #include "minorGems/io/file/FileInputStream.h" #include "minorGems/io/file/FileOutputStream.h" inline char *File::readFileContents() { int length; // text mode! unsigned char *data = readFileContents( &length, true ); if( data == NULL ) { return NULL; } char *dataString = new char[ length + 1 ]; memcpy( dataString, data, length ); dataString[ length ] = '\0'; delete [] data; return dataString; } inline unsigned char *File::readFileContents( int *outLength, char inTextMode ) { if( exists() ) { int length = getLength(); unsigned char *returnData = new unsigned char[ length ]; if( returnData != NULL ) { FileInputStream *input = new FileInputStream( this, inTextMode ); int numRead = input->read( returnData, length ); delete input; // in text mode, read length might not equal binary file length, // due to line end conversion if( numRead == length || ( inTextMode && numRead >= 0 ) ) { *outLength = numRead; return returnData; } else { delete [] returnData; return NULL; } } else { // failed to allocate this much memory return NULL; } } else { return NULL; } } inline char File::writeToFile( const char *inString ) { return writeToFile( (unsigned char *)inString, strlen( inString ) ); } inline char File::writeToFile( unsigned char *inData, int inLength ) { FileOutputStream *output = new FileOutputStream( this ); long numWritten = output->write( inData, inLength ); delete output; if( inLength == numWritten ) { return true; } else { return false; } } #include "Directory.h" inline char File::makeDirectory() { if( exists() ) { return false; } else { return Directory::makeDirectory( this ); } } #endif between-6+dfsg1.orig/minorGems/io/file/UniversalFileIO.h0000640000175000017500000000572411435543334021715 0ustar pabspabs// Jason Rohrer // UniversalFileIO.h /** * * Object that handles universal file reading and writing * Writes files as big endian, even on little endian machines * * Assumes that longs and floats are 32-bits * * Created 1-12-99 * Mods: * Jason Rohrer 1-30-2000 Fixed fwrite functions to work on little endian machines */ #ifndef UNIVERSAL_FILE_IO_INCLUDED #define UNIVERSAL_FILE_IO_INCLUDED #include class UniversalFileIO { public: UniversalFileIO(); long freadLong( FILE *f ); float freadFloat( FILE *f ); void fwriteLong( FILE *f, long x ); void fwriteFloat( FILE *f, float x ); private: char machineBigEndian; char bytesInLong; char bytesInFloat; }; inline UniversalFileIO::UniversalFileIO() : machineBigEndian( true ), bytesInLong( 4 ), bytesInFloat( 4 ) { // test whether machine is big endian long test = 1; char testChopped = (*(char*)&test); if( testChopped == 1 ) machineBigEndian = false; } inline long UniversalFileIO::freadLong( FILE *f ) { if( machineBigEndian ) { long returnVal; fread((void *)&returnVal, sizeof(long), 1, f); return returnVal; } else { unsigned char *buffer = new unsigned char[bytesInLong]; fread((void *)buffer, sizeof(char), bytesInLong, f); // now put the bytes into a long long returnVal = (long)( buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3] ); delete [] buffer; return returnVal; } } inline float UniversalFileIO::freadFloat( FILE *f ) { if( machineBigEndian ) { float returnVal; fread( (void *)&returnVal, sizeof(float), 1, f ); return returnVal; } else { unsigned char *buffer = new unsigned char[bytesInFloat]; fread( (void *)buffer, sizeof(char), bytesInFloat, f ); // now put the bytes into a long long temp = (long)(buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3]); delete [] buffer; return *((float *) &temp); // convert long into a float } } inline void UniversalFileIO::fwriteLong( FILE *f, long x ) { if( machineBigEndian ) { fwrite( (void *)&x, sizeof(long), 1, f ); } else { unsigned char *buffer = new unsigned char[bytesInLong]; buffer[0] = (unsigned char)(x >> 24); // put bytes from long into char buffer buffer[1] = (unsigned char)(x >> 16); buffer[2] = (unsigned char)(x >> 8); buffer[3] = (unsigned char)(x); fwrite( (void *)buffer, sizeof(char), bytesInLong, f ); } } inline void UniversalFileIO::fwriteFloat( FILE *f, float x ) { if( machineBigEndian ) { fwrite( (void *)&x, sizeof(float), 1, f ); } else { unsigned char *buffer = new unsigned char[bytesInFloat]; long temp = *((long*)&x); // convert float into long so that bit-wise ops can be performed buffer[0] = (unsigned char)(temp >> 24); // put bytes from float into char buffer buffer[1] = (unsigned char)(temp >> 16); buffer[2] = (unsigned char)(temp >> 8); buffer[3] = (unsigned char)(temp); fwrite( (void *)buffer, sizeof(char), bytesInFloat, f ); } } #endifbetween-6+dfsg1.orig/minorGems/io/file/Path.h0000640000175000017500000003556411435543334017616 0ustar pabspabs/* * Modification History * * 2001-February-12 Jason Rohrer * Created. * * 2001-May-11 Jason Rohrer * Added a version of getPathString that * returns a '\0' terminated string. * * 2001-September-21 Jason Rohrer * Added a missing include. * * 2001-September-23 Jason Rohrer * Added a copy function. * Made some comments more explicit. * Changed the constructor to allow for const path step strings. * * 2001-November-3 Jason Rohrer * Added a function for appending a string to a path. * Changed the interface to the main constructor. * * 2002-March-29 Jason Rohrer * Added Fortify inclusion. * * 2002-April-11 Jason Rohrer * Fixed a variable scoping bug. * * 2002-July-2 Jason Rohrer * Fixed a major memory leak in copy(). * * 2002-August-1 Jason Rohrer * Added support for path truncation. * Added support for parsing platform-dependent path strings. * * 2003-May-29 Jason Rohrer * Fixed a bug when an extra delimeters are at the end of the path. * Fixed a bug when string path consists only of root. * * 2003-June-2 Jason Rohrer * Fixed a bug in absolute path detection. * Added platform-specific functions for root and absolute path detection. * Fixed a memory bug when string path contains root only. * Fixed a path step bug when path is root. * Fixed bugs in truncate and append when non-default root string is used. * * 2005-August-29 Jason Rohrer * Fixed an uninitialized variable warning. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ #include "minorGems/common.h" #ifndef PATH_CLASS_INCLUDED #define PATH_CLASS_INCLUDED #include #include "minorGems/util/stringUtils.h" #ifdef FORTIFY #include "minorGems/util/development/fortify/fortify.h" #endif /** * Platform-independent file path interface. Contains * all of path except for file name. Thus, appending * a file name to the path will produce a complete file path. * * E.g., on Linux, file path: * temp/files/ * file name: * test.txt * full path: * temp/files/test.txt * * @author Jason Rohrer */ class Path { public: /** * Constructs a path. * * @param inPathSteps an array of c-strings representing * each step in the path, with no delimeters. * For example, { "temp", "files" } to represent * the linux path temp/files. * Must be destroyed by caller since copied internally. * @param inNumSteps the number of strings in the path. * @param inAbsolute set to true to make this an absolute * path. For example, in Linux, an absolute path * is one that starts with '/', as in /usr/include/. * The effects of inAbsolute vary by platform. * @param inRootString the root string for this path if it * is absolute, or NULL to specify a default root. * Defaults to NULL. * Must be destroyed by caller if non-NULL. */ Path( char **inPathSteps, int inNumSteps, char inAbsolute, char *inRootString = NULL ); /** * Constructs a path by parsing a platform-dependent path string. * * @param inPathSteps a \0-terminated string representing the path. * Must be destroyed by caller. */ Path( const char *inPathString ); ~Path(); /** * Returns a complete, platform-dependent string path. * * @param outLength pointer to where the path length, in * characters, will be returned. * * @return a new char array containing the path. Note * that the string is not terminated by '\0'. Must * be destroyed by the caller. */ char *getPathString( int *outLength ); /** * Returns a complete, platform-dependent string path, terminated * bye '\0'. * * @return a new char array containing the path. Note * that the string IS terminated by '\0'. Must * be destroyed by the caller. */ char *getPathStringTerminated(); /** * Gets the platform-specific path delimeter. * * Note that this function is implemented separately for * each supported platform. * * @return the path delimeter. */ static char getDelimeter(); /** * Gets start characters for an absolute path. * * Note that this function is implemented separately for * each supported platform. * * @param outLength pointer to where the string length, in * characters, will be returned. * * @return the absolute path start string characters. For * example, on Linux, this would be the string "/". * Must be destroyed by the caller. */ static char *getAbsoluteRoot( int *outLength ); /** * Gets whether a path string is absolute. * * Note that this function is implemented separately for * each supported platform. * * @param inPathString the string to check. * Must be destroyed by caller if non-const. * * @return true if the string is absolute, or false otherwise. */ static char isAbsolute( const char *inPathString ); /** * Extracts the root string from a path string. * * * @param inPathString the string to check. * Must be destroyed by caller if non-const. * * @return the root string, or NULL if inPathString is not * absolute. Must be destroyed by caller if non-NULL. */ static char *extractRoot( const char *inPathString ); /** * Gets whether a path string is a root path. * * Note that this function is implemented separately for * each supported platform. For example, on Unix, only "/" * is the root path, while on Windows, both "c:\" and "d:\" might * be root paths. * * @param inPathString the string to check. * Must be destroyed by caller if non-const. * * @return true if the string is a root string, or false otherwise. */ static char isRoot( const char *inPathString ); /** * Gets start string for an absolute path. * * @return the absolute path start string in \0-terminated form. * Must be destroyed by the caller. */ static char *getAbsoluteRootString(); /** * Copies this path. * * @return a new path that is a deep copy of this path. */ Path *copy(); /** * Constructs a new path by appending an additional * step onto this path. * * @param inStepString the step to add to this path. * Must be destroyed by caller if non-const. * * @return a new path with the extra step. * Must be destroyed by caller. */ Path *append( const char *inStepString ); /** * Constructs a new path by removing the last step from this path. * * @return a new path, or NULL if there is only one step in this path. * Must be destroyed by caller. */ Path *truncate(); /** * Gets the last step in this path. * * @return the last step. Must be destroyed by caller. */ char *getLastStep(); private: char **mPathSteps; int mNumSteps; int *mStepLength; char mAbsolute; // the root string of this path, if it is absolute char *mRootString; }; inline Path::Path( char **inPathSteps, int inNumSteps, char inAbsolute, char *inRootString ) : mNumSteps( inNumSteps ), mAbsolute( inAbsolute ), mRootString( NULL ) { if( inRootString != NULL ) { mRootString = stringDuplicate( inRootString ); } // copy the path steps mPathSteps = new char*[ mNumSteps ]; mStepLength = new int[ mNumSteps ]; for( int i=0; i 1 ) { // don't count tail end delimeters delimCount++; } currentDelimPointer = strstr( &( currentDelimPointer[1] ), delimString ); } // no delimeter at end of path mNumSteps = delimCount + 1; mPathSteps = new char*[ mNumSteps ]; mStepLength = new int[ mNumSteps ]; // now extract the chars between delimeters as path steps currentDelimPointer = strstr( pathRootSkipped, delimString ); int stepIndex = 0; currentDelimPointer[0] = '\0'; mPathSteps[ stepIndex ] = stringDuplicate( pathRootSkipped ); mStepLength[ stepIndex ] = strlen( mPathSteps[ stepIndex ] ); stepIndex++; while( currentDelimPointer != NULL ) { char *nextDelimPointer = strstr( &( currentDelimPointer[1] ), delimString ); if( nextDelimPointer != NULL ) { nextDelimPointer[0] = '\0'; } mPathSteps[ stepIndex ] = stringDuplicate( &( currentDelimPointer[1] ) ); mStepLength[ stepIndex ] = strlen( mPathSteps[ stepIndex ] ); stepIndex++; currentDelimPointer = nextDelimPointer; } } else { // no delimeters if( strlen( pathRootSkipped ) > 0 ) { mNumSteps = 1; mPathSteps = new char*[1]; mPathSteps[0] = stringDuplicate( pathRootSkipped ); mStepLength = new int[1]; mStepLength[0] = strlen( mPathSteps[0] ); } else { // path with root only mNumSteps = 0; mPathSteps = new char*[0]; mStepLength = new int[0]; } } delete [] delimString; delete [] pathStringCopy; } inline Path::~Path() { // delete each step for( int i=0; i= 1 ) { return stringDuplicate( mPathSteps[ mNumSteps - 1 ] ); } else { if( mAbsolute ) { if( mRootString != NULL ) { return stringDuplicate( mRootString ); } else { return getAbsoluteRootString(); } } else { // no path steps and not absolute... return stringDuplicate( "" ); } } } inline char *Path::getAbsoluteRootString() { int rootLength; char *root = getAbsoluteRoot( &rootLength ); char *rootString = new char[ rootLength + 1 ]; strncpy( rootString, root, rootLength ); // strncopy won't add termination if length limit reached rootString[ rootLength ] = '\0'; delete [] root; return rootString; } #endif between-6+dfsg1.orig/minorGems/io/file/linux/0000750000175000017500000000000011435543334017672 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/io/file/linux/PathLinux.cpp0000640000175000017500000000235111435543334022314 0ustar pabspabs/* * Modification History * * 2001-February-12 Jason Rohrer * Created. * * 2001-August-1 Jason Rohrer * Added missing length return value. * * 2003-June-2 Jason Rohrer * Added support for new path checking functions. * * 2010-May-18 Jason Rohrer * String parameters as const to fix warnings. */ #include "minorGems/io/file/Path.h" #include "minorGems/util/stringUtils.h" /* * Linux-specific path implementation. May be compatible * with other posix-complient systems. */ char Path::getDelimeter() { return '/'; } char *Path::getAbsoluteRoot( int *outLength ) { char *returnString = new char[1]; returnString[0] = '/'; *outLength = 1; return returnString; } char Path::isAbsolute( const char *inPathString ) { if( inPathString[0] == '/' ) { return true; } else { return false; } } char *Path::extractRoot( const char *inPathString ) { if( isAbsolute( inPathString ) ){ return stringDuplicate( "/" ); } else { return NULL; } } char Path::isRoot( const char *inPathString ) { if( strcmp( inPathString, "/" ) == 0 ) { return true; } else { return false; } } between-6+dfsg1.orig/minorGems/io/file/Directory.h0000640000175000017500000000262211435543334020653 0ustar pabspabs/* * Modification History * * 2003-January-23 Jason Rohrer * Created. * * * 2003-November-10 Jason Rohrer * Added makeDirectory function. */ #include "minorGems/common.h" #include "minorGems/io/file/File.h" #ifndef DIRECTORY_INCLUDED #define DIRECTORY_INCLUDED /** * Class of static directory functions. * * This class exists because most directory operations are * platform-dependent, and a large body of existing code * depends on a platform-independent File.h. * * @author Jason Rohrer. */ class Directory { public: /** * Removes a directory. * * The directory must be empty for this call to succeed. * * @param inFile the file representing the directory. * Must be destroyed by caller. * * @return true if the directory is removed successfully, or * false otherwise (for example, if the directory is not empy). */ static char removeDirectory( File *inFile ); /** * Makes a directory. * * @param inFile the file representing the directory. * Must be destroyed by caller. * * @return true if the directory is removed successfully, or * false otherwise (for example, if the directory is not empy). */ static char makeDirectory( File *inFile ); }; #endif between-6+dfsg1.orig/minorGems/io/file/win32/0000750000175000017500000000000011435543334017475 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/io/file/win32/DirectoryWin32.cpp0000640000175000017500000000140511435543334022771 0ustar pabspabs/* * Modification History * * 2003-January-23 Jason Rohrer * Created. * * 2003-November-10 Jason Rohrer * Added makeDirectory function. */ #include "minorGems/io/file/Directory.h" #include char Directory::removeDirectory( File *inFile ) { char *fileName = inFile->getFullFileName(); int result = _rmdir( fileName ); delete [] fileName; if( result == 0 ) { return true; } else { return false; } } char Directory::makeDirectory( File *inFile ) { char *stringName = inFile->getFullFileName(); int result = mkdir( stringName ); delete [] stringName; if( 0 == result ) { return true; } else { return false; } } between-6+dfsg1.orig/minorGems/io/file/win32/dirent.cpp0000640000175000017500000000654311435543334021477 0ustar pabspabs/* * Modification History * * 2002-April-7 Jason Rohrer * Added a mkdir wrapper for CodeWarrior. * * 2002-April-11 Jason Rohrer * Changed type of mode parameter to work with Visual C++. * Added missing include. * * 2002-July-22 Jason Rohrer * Commented out mkdir replacement function to work with new MSL. * * 2002-October-13 Jason Rohrer * Re-added mkdir wrapper function, since both CW4 and VC++ need it. */ /* Implementation of POSIX directory browsing functions and types for Win32. Kevlin Henney (mailto:kevlin@acm.org), March 1997. Copyright Kevlin Henney, 1997. All rights reserved. Permission to use, copy, modify, and distribute this software and its documentation for any purpose is hereby granted without fee, provided that this copyright and permissions notice appear in all copies and derivatives, and that no charge may be made for the software and its documentation except to cover cost of distribution. This software is supplied "as is" without express or implied warranty. But that said, if there are any problems please get in touch. */ #include #include #include #include #include #include struct DIR { long handle; /* -1 for failed rewind */ struct _finddata_t info; struct dirent result; /* d_name null iff first time */ char *name; /* NTBS */ }; DIR *opendir(const char *name) { DIR *dir = 0; if(name && name[0]) { size_t base_length = strlen(name); const char *all = /* the root directory is a special case... */ strchr("/\\", name[base_length - 1]) ? "*" : "/*"; if((dir = (DIR *) malloc(sizeof *dir)) != 0 && (dir->name = (char *) malloc(base_length + strlen(all) + 1)) != 0) { strcat(strcpy(dir->name, name), all); if((dir->handle = _findfirst(dir->name, &dir->info)) != -1) { dir->result.d_name = 0; } else /* rollback */ { free(dir->name); free(dir); dir = 0; } } else /* rollback */ { free(dir); dir = 0; errno = ENOMEM; } } else { errno = EINVAL; } return dir; } int closedir(DIR *dir) { int result = -1; if(dir) { if(dir->handle != -1) { result = _findclose(dir->handle); } free(dir->name); free(dir); } if(result == -1) /* map all errors to EBADF */ { errno = EBADF; } return result; } struct dirent *readdir(DIR *dir) { struct dirent *result = 0; if(dir && dir->handle != -1) { if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1) { result = &dir->result; result->d_name = dir->info.name; } } else { errno = EBADF; } return result; } void rewinddir(DIR *dir) { if(dir && dir->handle != -1) { _findclose(dir->handle); dir->handle = _findfirst(dir->name, &dir->info); dir->result.d_name = 0; } else { errno = EBADF; } } int mkdir( const char *pathname, unsigned int mode ) { return mkdir( pathname ); } between-6+dfsg1.orig/minorGems/io/file/win32/PathWin32.cpp0000640000175000017500000000336011435543334021723 0ustar pabspabs/* * Modification History * * 2001-February-12 Jason Rohrer * Created. * * 2001-March-4 Jason Rohrer * Fixed delimeter constants. * * 2001-August-1 Jason Rohrer * Added missing length return value. * * 2003-June-2 Jason Rohrer * Added support for new path checking functions. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ #include "minorGems/io/file/Path.h" #include "minorGems/util/stringUtils.h" /* * Windows-specific path implementation. */ char Path::getDelimeter() { return '\\'; } char *Path::getAbsoluteRoot( int *outLength) { // C:\ is the only root we can generically return char *returnString = new char[3]; returnString[0] = 'C'; returnString[1] = ':'; returnString[2] = '\\'; *outLength = 3; return returnString; } char Path::isAbsolute( const char *inPathString ) { // ignore first character, which will be drive letter if( inPathString[1] == ':' && inPathString[2] == '\\' ) { return true; } else { return false; } } char *Path::extractRoot( const char *inPathString ) { if( isAbsolute( inPathString ) ){ // copy path, then trim to only three characters char *pathCopy = stringDuplicate( inPathString ); pathCopy[ 3 ] = '\0'; char *trimmedCopy = stringDuplicate( pathCopy ); delete [] pathCopy; return trimmedCopy; } else { return NULL; } } char Path::isRoot( const char *inPathString ) { // must be of form "c:\" if( strlen( inPathString ) == 3 && inPathString[1] == ':' && inPathString[2] == '\\' ) { return true; } else { return false; } } between-6+dfsg1.orig/minorGems/io/file/win32/dirent.h0000640000175000017500000000327611435543334021144 0ustar pabspabs/* * Modification History * * 2002-April-7 Jason Rohrer * Added a mkdir wrapper for CodeWarrior. * * 2002-April-11 Jason Rohrer * Changed type of mode parameter to work with Visual C++. * Added missing macros. * * 2002-July-22 Jason Rohrer * Commented out mkdir replacement function to work with new MSL. * * 2002-October-13 Jason Rohrer * Re-added mkdir wrapper function, since both CW4 and VC++ need it. */ #include "minorGems/common.h" /* Declaration of POSIX directory browsing functions and types for Win32. Kevlin Henney (mailto:kevlin@acm.org), March 1997. Copyright Kevlin Henney, 1997. All rights reserved. Permission to use, copy, modify, and distribute this software and its documentation for any purpose is hereby granted without fee, provided that this copyright and permissions notice appear in all copies and derivatives, and that no charge may be made for the software and its documentation except to cover cost of distribution. */ #ifndef DIRENT_INCLUDED #define DIRENT_INCLUDED typedef struct DIR DIR; struct dirent { char *d_name; }; DIR *opendir(const char *); int closedir(DIR *); struct dirent *readdir(DIR *); void rewinddir(DIR *); #include /** * The Metrowerks Standard Library seems * to have only a 1-parameter mkdir command in sys/stat.h. */ int mkdir( const char *pathname, unsigned int mode ); // make sure our needed macros are defined // S_IFMT and S_IFDIR seem to be defined everywhere #ifndef __S_ISTYPE #define __S_ISTYPE(mode, mask) (((mode) & S_IFMT) == (mask)) #endif #ifndef S_ISDIR #define S_ISDIR(mode) __S_ISTYPE((mode), S_IFDIR) #endif #endif between-6+dfsg1.orig/minorGems/io/file/test/0000750000175000017500000000000011435543334017512 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/io/file/test/testPath.cpp0000640000175000017500000000112211435543334022007 0ustar pabspabs/* * Modification History * * 2002-August-1 Jason Rohrer * Created. */ #include "Path.h" #include int main() { char *pathString = "/test/this/thing"; printf( "using path string = %s\n", pathString ); printf( "Constructing path.\n" ); Path *path = new Path( pathString ); printf( "Extracting path string.\n" ); char *extractedPathString = path->getPathStringTerminated(); printf( "extracted path string = %s\n", extractedPathString ); delete [] extractedPathString; delete path; return 1; } between-6+dfsg1.orig/minorGems/io/file/test/testChildFiles.cpp0000640000175000017500000000223111435543334023123 0ustar pabspabs/* * Modification History * * 2004-January-4 Jason Rohrer * Created. */ /** * A test program for the various child file functions in File.h * * @author Jason Rohrer. */ #include "minorGems/io/file/File.h" int main( int inNumArgs, char **inArgs ) { char *fileName = "linux"; if( inNumArgs > 1 ) { fileName = inArgs[1]; } File *testFile = new File( NULL, fileName ); int numChildren; File **childFiles = testFile->getChildFiles( &numChildren ); printf( "child files:\n" ); for( int i=0; igetFullFileName(); printf( " %s\n", fullName ); delete [] fullName; delete childFiles[i]; } delete [] childFiles; childFiles = testFile->getChildFilesRecursive( 10, &numChildren ); printf( "recursive child files:\n" ); for( int i=0; igetFullFileName(); printf( " %s\n", fullName ); delete [] fullName; delete childFiles[i]; } delete [] childFiles; delete testFile; return 0; } between-6+dfsg1.orig/minorGems/io/serialPort/0000750000175000017500000000000011435543334017740 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/io/serialPort/testSerialPort.cpp0000640000175000017500000000101011435543334023421 0ustar pabspabs #include "SerialPort.h" #include int main() { printf( "Constructing serial port.\n" ); SerialPort *port = new SerialPort( 4800, SerialPort::PARITY_NONE, 8, 1 ); char *line = port->receiveLine(); // specific to GPS unit port->sendLine( "ASTRAL" ); while( line != NULL ) { printf( "received: %s\n", line ); delete [] line; line = port->receiveLine(); } printf( "Deleting serial port.\n" ); delete port; return 0; } between-6+dfsg1.orig/minorGems/io/serialPort/linux/0000750000175000017500000000000011435543334021077 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/io/serialPort/linux/SerialPortLinux.cpp0000640000175000017500000001477511435543334024726 0ustar pabspabs/* * Modification History * * 2003-February-17 Jason Rohrer * Created. * * 2003-April-4 Jason Rohrer * Added function for dumping the read buffer. */ #include "minorGems/io/serialPort/SerialPort.h" #include "minorGems/util/stringUtils.h" // Much of the code in this implementation was copied // from the Serial Programming FAQ, by Gary Frefking // http://en.tldp.org/HOWTO/Serial-Programming-HOWTO/ #include #include #include #include #include #include // baudrate settings are defined in , which is // included by class LinuxSerialPortObject { public: int mFileHandle; struct termios mOldTermIO; }; SerialPort::SerialPort( int inBaud, int inParity, int inDataBits, int inStopBits ) { int fileHandle = open( "/dev/ttyS0", O_RDWR | O_NOCTTY ); if( fileHandle < 0 ) { mNativeObjectPointer = NULL; } else { LinuxSerialPortObject *serialPortObject = new LinuxSerialPortObject(); serialPortObject->mFileHandle = fileHandle; mNativeObjectPointer = (void *)serialPortObject; struct termios newTermIO; //save current serial port settings tcgetattr( fileHandle, &( serialPortObject->mOldTermIO ) ); // clear struct for new port settings bzero( &newTermIO, sizeof( newTermIO ) ); unsigned int baudRate; switch( inBaud ) { case 1200: baudRate = B1200; break; case 2400: baudRate = B2400; break; case 4800: baudRate = B4800; break; case 9600: baudRate = B9600; break; case 19200: baudRate = B19200; break; case 38400: baudRate = B38400; break; case 57600: baudRate = B57600; break; default: break; } unsigned int parity = 0; switch( inParity ) { case SerialPort::PARITY_NONE: // disable parity parity = 0; break; case SerialPort::PARITY_EVEN: // enable parity, defaults to even parity = PARENB; break; case SerialPort::PARITY_ODD: // enable parity, and set to odd parity = PARENB | PARODD; break; default: break; } unsigned int dataBits = 0; switch( inDataBits ) { case 5: dataBits = CS5; break; case 6: dataBits = CS6; break; case 7: dataBits = CS7; break; case 8: dataBits = CS8; break; default: break; } unsigned int stopBits = 0; switch( inStopBits ) { case 1: stopBits = 0; break; case 2: stopBits = CSTOPB; break; default: break; } newTermIO.c_cflag = baudRate | parity | dataBits | stopBits | CLOCAL | CREAD; /* IGNPAR : ignore bytes with parity errors ICRNL : map CR to NL (otherwise a CR input on the other computer will not terminate input) IGNCR : ignore CR, so only one line is read when other machine sends CRLF otherwise make device raw (no other input processing) */ newTermIO.c_iflag = IGNPAR | ICRNL | IGNCR; /* Raw output. */ newTermIO.c_oflag = 0; /* ICANON : enable canonical input disable all echo functionality, and don't send signals to calling program */ newTermIO.c_lflag = ICANON; /* now clean the modem line and activate the settings for the port */ tcflush( fileHandle, TCIFLUSH ); tcsetattr( fileHandle, TCSANOW, &newTermIO ); } } SerialPort::~SerialPort() { if( mNativeObjectPointer != NULL ) { LinuxSerialPortObject *serialPortObject = (LinuxSerialPortObject *)mNativeObjectPointer; int fileHandle = serialPortObject->mFileHandle; tcsetattr( fileHandle, TCSANOW, &( serialPortObject->mOldTermIO ) ); delete serialPortObject; } } int SerialPort::sendLine( char *inLine ) { if( mNativeObjectPointer != NULL ) { LinuxSerialPortObject *serialPortObject = (LinuxSerialPortObject *)mNativeObjectPointer; int fileHandle = serialPortObject->mFileHandle; int stringLength = strlen( inLine ); int numWritten = write( fileHandle, inLine, stringLength ); char *endLineString = "\n"; int numWrittenEndLine = write( fileHandle, endLineString, 1 ); if( numWritten == stringLength && numWrittenEndLine == 1 ) { return 1; } else { return -1; } } else { return -1; } } char *SerialPort::receiveLine() { if( mNativeObjectPointer != NULL ) { LinuxSerialPortObject *serialPortObject = (LinuxSerialPortObject *)mNativeObjectPointer; int fileHandle = serialPortObject->mFileHandle; char *buffer = new char[500]; int numRead = read( fileHandle, buffer, 500 ); char *returnString; if( numRead != -1 ) { buffer[ numRead ] = '\0'; returnString = stringDuplicate( buffer ); } else { returnString = NULL; } delete [] buffer; return returnString; } else { return NULL; } } void SerialPort::dumpReceiveBuffer() { if( mNativeObjectPointer != NULL ) { LinuxSerialPortObject *serialPortObject = (LinuxSerialPortObject *)mNativeObjectPointer; int fileHandle = serialPortObject->mFileHandle; // from man page: // flushes data received but not read tcflush( fileHandle, TCIFLUSH ); } } between-6+dfsg1.orig/minorGems/io/serialPort/SerialPortFromFile.cpp0000640000175000017500000000266211435543334024163 0ustar pabspabs/* * Modification History * * 2003-March-28 Jason Rohrer * Created. */ #include "minorGems/io/serialPort/SerialPort.h" #include "minorGems/util/stringUtils.h" #include SerialPort::SerialPort( int inBaud, int inParity, int inDataBits, int inStopBits ) { FILE *file = fopen( "gpscap.txt", "r" ); mNativeObjectPointer = file; } SerialPort::~SerialPort() { if( mNativeObjectPointer != NULL ) { FILE *file = (FILE *)mNativeObjectPointer; fclose( file ); } } int SerialPort::sendLine( char *inLine ) { return 1; } char *SerialPort::receiveLine() { if( mNativeObjectPointer != NULL ) { FILE *file = (FILE *)mNativeObjectPointer; char *buffer = new char[500]; // read up to first newline int index = 0; char lastCharRead = (char)getc( file ); while( lastCharRead != '\n' && index < 499 ) { buffer[index] = lastCharRead; lastCharRead = (char)getc( file ); index++; } char *returnString; if( index > 0 ) { buffer[ index ] = '\0'; returnString = stringDuplicate( buffer ); } else { returnString = NULL; } delete [] buffer; return returnString; } else { return NULL; } } between-6+dfsg1.orig/minorGems/io/serialPort/win32/0000750000175000017500000000000011435543334020702 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/io/serialPort/win32/COMPort.h0000640000175000017500000000672311435543334022347 0ustar pabspabs/* * Modification History * * 2003-April-4 Jason Rohrer * Added function for dumping the read buffer. */ //============================================================================= // General component library for WIN32 // Copyright (C) 2000, UAB BBDSoft ( http://www.bbdsoft.com/ ) // // This material is provided "as is", with absolutely no warranty expressed // or implied. Any use is at your own risk. // // Permission to use or copy this software for any purpose is hereby granted // without fee, provided the above notices are retained on all copies. // Permission to modify the code and to distribute modified code is granted, // provided the above notices are retained, and a notice that the code was // modified is included with the above copyright notice. // // The author of this program may be contacted at developers@bbdsoft.com //============================================================================= #ifndef _COMPORT_ #define _COMPORT_ //----------------------------------------------------------------------------- class COMPort { public: enum Parity { None = 0 , Odd , Even , Mark , Space }; enum DataBits { db4 = 4 , db5 , db6 , db7 , db8 }; enum StopBits { sb1 = 0, sb15, sb2 }; enum BitRate { br110 = 110, br300 = 300, br600 = 600, br1200 = 1200, br2400 = 2400, br4800 = 4800, br9600 = 9600, br19200 = 19200, br38400 = 38400, br56000 = 56000, br57600 = 57600, br115200 = 115200, br256000 = 256000 }; // for function getModemSignals struct MSPack { unsigned char DTR : 1; unsigned char RTS : 1; unsigned char : 2; unsigned char CTS : 1; unsigned char DSR : 1; unsigned char RI : 1; unsigned char DCD : 1; }; COMPort ( const char * const portName ); ~COMPort (); // I/O operations char read (); COMPort & write (const char inChar); unsigned long read ( void * , const unsigned long count ); unsigned long write ( const void * , const unsigned long count ); // dumps unread characters in the receive buffer void dumpReceiveBuffer(); COMPort& setBitRate ( unsigned long Param ); unsigned long bitRate () const; COMPort& setParity ( Parity Param ); Parity parity () const; COMPort& setDataBits ( DataBits Param ); DataBits dataBits () const; COMPort& setStopBits ( StopBits Param ); StopBits stopBits () const; COMPort & setHandshaking ( bool inHandshaking = true ); COMPort& setLineCharacteristics ( char * Param ); unsigned long getMaximumBitRate () const; COMPort & setxONxOFF ( bool Param = true); bool isxONxOFF () const; MSPack getModemSignals () const; COMPort& setBlockingMode ( unsigned long inReadInterval = 0 , unsigned long inReadMultiplyer = 0 , unsigned long inReadConstant = 0 ); protected: private: // disable copy constructor and assignment operator COMPort (const COMPort &); COMPort& operator= (const COMPort &); void getState () const; COMPort& setState (); unsigned thePortHandle; char * theDCB; }; // End of COMPort class declaration #endif between-6+dfsg1.orig/minorGems/io/serialPort/win32/SerialPortWin32.cpp0000640000175000017500000001036511435543334024323 0ustar pabspabs/* * Modification History * * 2003-March-24 Jason Rohrer * Created. * * 2003-March-26 Jason Rohrer * Fixed a line parsing bug (lines end with newline, not CR). * * 2003-April-4 Jason Rohrer * Added function for dumping the read buffer. */ #include "minorGems/io/serialPort/SerialPort.h" #include "minorGems/util/stringUtils.h" // For now, we are using BBDSoft's COM port code #include "COMPort.h" SerialPort::SerialPort( int inBaud, int inParity, int inDataBits, int inStopBits ) { COMPort *port = new COMPort( "COM1" ); port->setHandshaking( false ); unsigned long baudRate = COMPort::br2400; switch( inBaud ) { case 1200: baudRate = COMPort::br1200; break; case 2400: baudRate = COMPort::br2400; break; case 4800: baudRate = COMPort::br4800; break; case 9600: baudRate = COMPort::br9600; break; case 19200: baudRate = COMPort::br19200; break; case 38400: baudRate = COMPort::br38400; break; case 57600: baudRate = COMPort::br57600; break; default: break; } port->setBitRate( baudRate ); switch( inParity ) { case SerialPort::PARITY_NONE: port->setParity( COMPort::None ); break; case SerialPort::PARITY_EVEN: port->setParity( COMPort::Even ); break; case SerialPort::PARITY_ODD: port->setParity( COMPort::Odd ); break; default: port->setParity( COMPort::None ); break; } switch( inDataBits ) { case 5: port->setDataBits( COMPort::db5 ); break; case 6: port->setDataBits( COMPort::db6 ); break; case 7: port->setDataBits( COMPort::db7 ); break; case 8: port->setDataBits( COMPort::db8 ); break; default: port->setDataBits( COMPort::db8 ); break; } switch( inStopBits ) { case 1: port->setStopBits( COMPort::sb1 ); break; case 2: port->setStopBits( COMPort::sb2 ); break; default: port->setStopBits( COMPort::sb1 ); break; } mNativeObjectPointer = (void *)port; } SerialPort::~SerialPort() { if( mNativeObjectPointer != NULL ) { COMPort *port = (COMPort *)mNativeObjectPointer; delete port; } } int SerialPort::sendLine( char *inLine ) { if( mNativeObjectPointer != NULL ) { COMPort *port = (COMPort *)mNativeObjectPointer; int stringLength = strlen( inLine ); int numWritten = port->write( (void *)inLine, stringLength ); char *endLineString = "\n"; int numWrittenEndLine = port->write( (void *)endLineString, 1 ); if( numWritten == stringLength && numWrittenEndLine == 1 ) { return 1; } else { return -1; } } else { return -1; } } char *SerialPort::receiveLine() { if( mNativeObjectPointer != NULL ) { COMPort *port = (COMPort *)mNativeObjectPointer; char *buffer = new char[500]; // read up to first newline int index = 0; char lastCharRead = port->read(); while( lastCharRead != '\n' && index < 499 ) { buffer[index] = lastCharRead; lastCharRead = port->read(); index++; } char *returnString; if( index > 0 ) { buffer[ index ] = '\0'; returnString = stringDuplicate( buffer ); } else { returnString = NULL; } delete [] buffer; return returnString; } else { return NULL; } } void SerialPort::dumpReceiveBuffer() { if( mNativeObjectPointer != NULL ) { COMPort *port = (COMPort *)mNativeObjectPointer; port->dumpReceiveBuffer(); } } between-6+dfsg1.orig/minorGems/io/serialPort/win32/COMPort.cpp0000640000175000017500000002471111435543334022677 0ustar pabspabs/* * Modification History * * 2003-April-4 Jason Rohrer * Added function for dumping the read buffer. */ //============================================================================= // General component library for WIN32 // Copyright (C) 2000, UAB BBDSoft ( http://www.bbdsoft.com/ ) // // This material is provided "as is", with absolutely no warranty expressed // or implied. Any use is at your own risk. // // Permission to use or copy this software for any purpose is hereby granted // without fee, provided the above notices are retained on all copies. // Permission to modify the code and to distribute modified code is granted, // provided the above notices are retained, and a notice that the code was // modified is included with the above copyright notice. // // The author of this program may be contacted at developers@bbdsoft.com //============================================================================= #ifndef _COMPORT_ #include "ComPort.h" #endif #ifndef _WINDOWS_ #define WIN32_LEAN_AND_MEAN #include #endif #ifndef _STDEXCEPT_ #include #endif using namespace std; //---------------------------------------------------------------------------- COMPort::COMPort ( const char * const portName ) : theDCB (NULL) { thePortHandle = (unsigned ) CreateFile ( portName , GENERIC_READ | GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , FILE_FLAG_NO_BUFFERING , NULL ); if (thePortHandle == HFILE_ERROR) { throw runtime_error ("COMPort: failed to open."); } // endif theDCB = new char [sizeof(DCB)]; getState(); setBlockingMode(); setHandshaking(); } // end constructor //---------------------------------------------------------------------------- COMPort::~COMPort() { delete [] theDCB; // close serial port device if (CloseHandle ((HANDLE)thePortHandle) == FALSE ) { throw runtime_error ("COMPort: failed to close."); } // endif } // end destructor //---------------------------------------------------------------------------- void COMPort::getState () const { if (!GetCommState ( (HANDLE) thePortHandle , (LPDCB) theDCB ) ) { throw runtime_error ("COMPort: could not retrieve serial port state."); } // endif } // end COMPort::getState () const //---------------------------------------------------------------------------- COMPort& COMPort::setState () { if (!SetCommState ( (HANDLE) thePortHandle , (LPDCB) theDCB ) ) { throw runtime_error ("COMPort: could not modify serial port state."); } // endif return *this; } // end COMPort::setState () //----------------------------------------------------------------------------- COMPort& COMPort::setBitRate ( unsigned long Param ) { DCB & aDCB = *((LPDCB)theDCB); aDCB.BaudRate = Param; return setState(); } // end COMPort::setBitRate (..) //----------------------------------------------------------------------------- unsigned long COMPort::bitRate() const { DCB & aDCB = *((LPDCB)theDCB); return aDCB.BaudRate; } // end COMPort::bitRate () const //----------------------------------------------------------------------------- COMPort& COMPort::setLineCharacteristics( char * inConfig ) { COMMTIMEOUTS aTimeout; if ( !BuildCommDCBAndTimeouts ( inConfig , (LPDCB)theDCB , &aTimeout ) ) { throw runtime_error ("COMPort: could not set line characteristics."); } // endif if ( ! SetCommTimeouts ( (HANDLE(thePortHandle)) , &aTimeout ) ) { throw runtime_error ("COMPort: could not set line characteristics."); } // endif return setState(); } //---------------------------------------------------------------------------- char COMPort::read () { char buffer; DWORD charsRead = 0; do { if (! ReadFile ( (HANDLE(thePortHandle)) , &buffer , sizeof(char) , &charsRead , NULL ) ) { throw runtime_error ("COMPort: read failed."); } // endif } while ( !charsRead ); return buffer; } // end COMPort::read() //---------------------------------------------------------------------------- void COMPort::dumpReceiveBuffer () { PurgeComm( (HANDLE(thePortHandle)) , PURGE_RXCLEAR ); } // end COMPort::dumpReceiveBuffer() //---------------------------------------------------------------------------- unsigned long COMPort::read ( void *inBuffer , const unsigned long inCharsReq ) { DWORD charsRead = 0; if ( !ReadFile ( (HANDLE(thePortHandle)) , inBuffer , inCharsReq , &charsRead , NULL ) ) { throw runtime_error ("COMPort: read failed."); } // endif return charsRead; } // end COMPort::read (..) //---------------------------------------------------------------------------- COMPort & COMPort::write ( const char inChar ) { char buffer = inChar; DWORD charsWritten = 0; if ( !WriteFile ( (HANDLE(thePortHandle)) , &buffer , sizeof(char) , &charsWritten , NULL ) ) { throw runtime_error ("COMPort: write failed."); } // endif return *this; } // end COMPort::write (..) //---------------------------------------------------------------------------- unsigned long COMPort::write ( const void *inBuffer , const unsigned long inBufSize ) { DWORD charsWritten = 0; if ( !WriteFile ( (HANDLE(thePortHandle)) , inBuffer , inBufSize , &charsWritten , NULL ) ) { throw runtime_error ("COMPort: write failed."); } // endif return charsWritten; } // end COMPort::write() //----------------------------------------------------------------------------- COMPort& COMPort::setxONxOFF ( bool Param ) { DCB & aDCB = *((LPDCB)theDCB); aDCB.fOutX = Param ? 1 : 0; aDCB.fInX = Param ? 1 : 0; return setState(); } // end COMPort::setxONxOFF (..) //----------------------------------------------------------------------------- bool COMPort::isxONxOFF () const { DCB & aDCB = *((LPDCB)theDCB); return (aDCB.fOutX && aDCB.fInX); } // end COMPort::isxONxOFF () const //---------------------------------------------------------------------------- COMPort& COMPort::setBlockingMode ( unsigned long inReadInterval , unsigned long inReadMultiplyer , unsigned long inReadConstant ) { COMMTIMEOUTS commTimeout; if ( !GetCommTimeouts ( (HANDLE(thePortHandle)) , &commTimeout ) ) { throw runtime_error ("COMPort: failed to retrieve timeouts."); } // endif commTimeout.ReadIntervalTimeout = inReadInterval; if ( inReadInterval==MAXDWORD ) { commTimeout.ReadTotalTimeoutMultiplier = 0; commTimeout.ReadTotalTimeoutConstant = 0; } else { commTimeout.ReadTotalTimeoutMultiplier = inReadMultiplyer; commTimeout.ReadTotalTimeoutConstant = inReadConstant; } // endifelse if ( !SetCommTimeouts ( (HANDLE(thePortHandle)) , &commTimeout ) ) { throw runtime_error ("COMPort: failed to modify timeouts."); } // endif return *this; } // end COMPort::setBlockingMode (..) //----------------------------------------------------------------------------- COMPort & COMPort::setHandshaking ( bool inHandshaking ) { DCB & aDCB = *((LPDCB)theDCB); if (inHandshaking) { aDCB.fOutxCtsFlow = TRUE; aDCB.fOutxDsrFlow = FALSE; aDCB.fRtsControl = RTS_CONTROL_HANDSHAKE; } else { aDCB.fOutxCtsFlow = FALSE; aDCB.fOutxDsrFlow = FALSE; aDCB.fRtsControl = RTS_CONTROL_ENABLE; } // endifelse return setState(); } // end COMPort::setHandshaking (..) //----------------------------------------------------------------------------- unsigned long COMPort::getMaximumBitRate() const { COMMPROP aProp; if ( !GetCommProperties ( (HANDLE)thePortHandle , &aProp ) ) { throw runtime_error ("COMPort: failed to retrieve port properties."); } // endif return aProp.dwMaxBaud; } // end COMPort::getMaximumBitRate () const //----------------------------------------------------------------------------- COMPort::MSPack COMPort::getModemSignals() const { MSPack aPack; // 1 bit - DTR, 2 - bit RTS (output signals) // 4 bit - CTS, 5 bit - DSR, 6 bit - RI, 7 bit - DCD (input signals) if ( !GetCommModemStatus ( (HANDLE)thePortHandle , (LPDWORD)&aPack ) ) { throw runtime_error ("COMPort: failed to retrieve modem signals."); } // endif return aPack; } // end COMPort::getModemSignals () const //----------------------------------------------------------------------------- COMPort& COMPort::setParity ( Parity Param ) { DCB & aDCB = *((LPDCB)theDCB); aDCB.Parity = Param; return setState(); } // end COMPort::setParity (..) //----------------------------------------------------------------------------- COMPort& COMPort::setDataBits ( DataBits Param ) { DCB & aDCB = *((LPDCB)theDCB); aDCB.ByteSize = Param; return setState(); } // end COMPort::setDataBits (..) //----------------------------------------------------------------------------- COMPort& COMPort::setStopBits ( StopBits Param ) { DCB & aDCB = *((LPDCB)theDCB); aDCB.StopBits = Param; return setState(); } // end COMPort::setStopBits (..) //----------------------------------------------------------------------------- COMPort::Parity COMPort::parity () const { DCB & aDCB = *((LPDCB)theDCB); return (COMPort::Parity)aDCB.Parity; } // end COMPort::parity () const //----------------------------------------------------------------------------- COMPort::DataBits COMPort::dataBits () const { DCB & aDCB = *((LPDCB)theDCB); return (COMPort::DataBits)aDCB.ByteSize; } // end COMPort::dataBits () const //----------------------------------------------------------------------------- COMPort::StopBits COMPort::stopBits () const { DCB & aDCB = *((LPDCB)theDCB); return (COMPort::StopBits)aDCB.StopBits; } // end COMPort::stopBits () cosnt between-6+dfsg1.orig/minorGems/io/serialPort/testSerialPortCompile0000750000175000017500000000011511435543334024160 0ustar pabspabsg++ -o testSerialPort -I../../.. linux/SerialPortLinux.cpp testSerialPort.cppbetween-6+dfsg1.orig/minorGems/io/serialPort/SerialPort.h0000640000175000017500000000430611435543334022201 0ustar pabspabs/* * Modification History * * 2003-February-17 Jason Rohrer * Created. * * 2003-April-4 Jason Rohrer * Added function for dumping the read buffer. */ #ifndef SERIAL_PORT_INCLUDED #define SERIAL_PORT_INCLUDED /** * Serial port. * * Note: Implementation for the functions defined here is provided * separately for each platform (in the mac/ linux/ and win32/ * subdirectories). * * @author Jason Rohrer */ class SerialPort { public: static const int PARITY_NONE = 0; static const int PARITY_EVEN = 1; static const int PARITY_ODD = 2; /** * Constructs a serial port. * * @param inBaud the baud rate. * @param inParity the parity, one of SerialPort:: PARITY_NONE, * PARITY_EVEN, or PARITY_ODD. * @param inDataBits the number of data bits, 5, 6, 7, or 8. * @param inStopBits the number of stop bits, 1 or 2. */ SerialPort( int inBaud, int inParity, int inDataBits, int inStopBits ); ~SerialPort(); /** * Sends a line of text through this serial port. * * @param inLine the \0-terminated line of text to send. * Should not contain newline characters. * Must be destroyed by caller if non-const. * * @return 1 if the line was sent successfully, * or -1 for a port error. */ int sendLine( char *inLine ); /** * Receives a line of text from this serial port. * * @return the read line as a \0-terminated string with end of * line characters included, or NULL for a port error. * Must be destroyed by caller if non-NULL. */ char *receiveLine(); /** * Discards all characters in the receive buffer, including * unread characters. * * Can be used to recover from buffer overflow problems. */ void dumpReceiveBuffer(); private: /** * Used for platform-specific implementations. */ void *mNativeObjectPointer; }; #endif between-6+dfsg1.orig/minorGems/io/InputStream.h0000640000175000017500000000735011435543334020246 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. * * 2001-January-9 Jason Rohrer * Changed the "number of bytes read" parameter and return value * to longs. * * 2001-February-3 Jason Rohrer * Added a readDouble function to fix platform-specific double problems. * Also added a readLong function for completeness. Implemented * these functions, making use of the new TypeIO interface. * * 2001-February-12 Jason Rohrer * Changed to subclass Stream. * * 2002-March-9 Jason Rohrer * Added a readByte() function. * * 2002-March-31 Jason Rohrer * Made destructor virtual so it works with subclasses. * * 2004-May-9 Jason Rohrer * Added support for shorts. */ #include "minorGems/common.h" #ifndef INPUT_STREAM_CLASS_INCLUDED #define INPUT_STREAM_CLASS_INCLUDED #include "Stream.h" #include "TypeIO.h" /** * Interface for a byte input stream. * * @author Jason Rohrer */ class InputStream : public Stream { public: InputStream(); virtual ~InputStream(); /** * Reads bytes from this stream. * * @param inBuffer the buffer where read bytes will be put. * Must be pre-allocated memory space. * @param inNumBytes the number of bytes to read from the stream. * * @return the number of bytes read successfully, * or -1 for a stream error. */ virtual long read( unsigned char *inBuffer, long inNumBytes ) = 0; /** * Reads a byte from this stream. * * @param outByte pointer to where the byte should be stored. * * @return the number of bytes read successfully, or -1 for a * stream error. */ long readByte( unsigned char *outByte ); /** * Reads a double from the stream in a platform-independent way. * * @param outDouble pointer to where the double should be stored. * * @return the number of bytes read successfully, or -1 for a * stream error. */ long readDouble( double *outDouble ); /** * Reads a long from the stream in a platform-independent way. * * @param outLong pointer to where the long should be stored. * * @return the number of bytes read successfully, or -1 for a * stream error. */ long readLong( long *outLong ); /** * Reads a short from the stream in a platform-independent way. * * @param outShort pointer to where the short should be stored. * * @return the number of bytes read successfully, or -1 for a * stream error. */ long readShort( short *outShort ); private: unsigned char *mDoubleBuffer; unsigned char *mLongBuffer; unsigned char *mShortBuffer; unsigned char *mByteBuffer; }; inline InputStream::InputStream() : mDoubleBuffer( new unsigned char[8] ), mLongBuffer( new unsigned char[4] ), mShortBuffer( new unsigned char[2] ), mByteBuffer( new unsigned char[1] ) { } inline InputStream::~InputStream() { delete [] mDoubleBuffer; delete [] mShortBuffer; delete [] mLongBuffer; delete [] mByteBuffer; } inline long InputStream::readByte( unsigned char *outByte ) { int numBytes = read( mByteBuffer, 1 ); *outByte = mByteBuffer[0]; return numBytes; } inline long InputStream::readDouble( double *outDouble ) { int numBytes = read( mDoubleBuffer, 8 ); *outDouble = TypeIO::bytesToDouble( mDoubleBuffer ); return numBytes; } inline long InputStream::readLong( long *outLong ) { int numBytes = read( mLongBuffer, 4 ); *outLong = TypeIO::bytesToLong( mLongBuffer ); return numBytes; } inline long InputStream::readShort( short *outShort ) { int numBytes = read( mShortBuffer, 4 ); *outShort = TypeIO::bytesToShort( mShortBuffer ); return numBytes; } #endif between-6+dfsg1.orig/minorGems/io/TypeIO.h0000640000175000017500000000650611435543334017146 0ustar pabspabs/* * Modification History * * 2001-February-3 Jason Rohrer * Created. * Fixed parameter names to match convention. * * 2003-January-11 Jason Rohrer * Added missing casts. * * 2004-May-9 Jason Rohrer * Added support for shorts. */ #include "minorGems/common.h" #ifndef TYPE_IO_INCLUDED #define TYPE_IO_INCLUDED /** * Interfaces for platform-independent type input and output. * * The specification for the input/output format for types is as follows: * * Types should be output in the order and format that a big-endian Linux * outputs them by default. * * Note that minorGems/numtest.cpp can be used to test how doubles are * stored on a specific platform. * * @author Jason Rohrer */ class TypeIO { public: /** * Converts an 32-bit integer to a byte array in a * platform-independent fashion. * * @param inInt the integer to convert to a byte array. * @param outBytes preallocated array where bytes will be returned. */ static void longToBytes( long inInt, unsigned char *outBytes ); /** * Converts a 4-byte array to a 32-bit integer * platform-independent fashion. * * @param inBytes array of bytes to convert. * * @return the integer represented by the bytes. */ static long bytesToLong( unsigned char *inBytes ); /** * Converts an 16-bit integer to a byte array in a * platform-independent fashion. * * @param inInt the integer to convert to a byte array. * @param outBytes preallocated array where bytes will be returned. */ static void shortToBytes( short inInt, unsigned char *outBytes ); /** * Converts a 2-byte array to a 16-bit integer * platform-independent fashion. * * @param inBytes array of bytes to convert. * * @return the integer represented by the bytes. */ static short bytesToShort( unsigned char *inBytes ); /** * Converts an 64-bit float to a byte array in a * platform-independent fashion. * * @param inDouble the double to convert to a byte array. * @param outBytes preallocated array where bytes will be returned. */ static void doubleToBytes( double inDouble, unsigned char *outBytes ); /** * Converts a 8-byte array to a 64-bit float * platform-independent fashion. * * @param inBytes array of bytes to convert. * * @return the double represented by the bytes. */ static double bytesToDouble( unsigned char *inBytes ); }; // for now, these long IO functions can be implemented in the same way // on every platform. inline void TypeIO::longToBytes( long inInt, unsigned char *outBytes ) { // use a big-endian conversion outBytes[0] = (unsigned char)( inInt >> 24 & 0xFF ); outBytes[1] = (unsigned char)( inInt >> 16 & 0xFF ); outBytes[2] = (unsigned char)( inInt >> 8 & 0xFF ); outBytes[3] = (unsigned char)( inInt & 0xFF ); } inline long TypeIO::bytesToLong( unsigned char *inBytes ) { return (long)( inBytes[0] << 24 | inBytes[1] << 16 | inBytes[2] << 8 | inBytes[3] ); } inline void TypeIO::shortToBytes( short inInt, unsigned char *outBytes ) { // use a big-endian conversion outBytes[0] = (unsigned char)( inInt >> 8 & 0xFF ); outBytes[1] = (unsigned char)( inInt & 0xFF ); } inline short TypeIO::bytesToShort( unsigned char *inBytes ) { return (short)( inBytes[0] << 8 | inBytes[1] ); } #endif between-6+dfsg1.orig/minorGems/io/pipedStreamTest.cpp0000640000175000017500000000305611435543334021442 0ustar pabspabs/* * Modification History * * 2001-February-19 Jason Rohrer * Created. */ #include #include "PipedStream.h" #include "minorGems/util/random/StdRandomSource.h" // test function for piped streams int main() { PipedStream *stream = new PipedStream; InputStream *inStream = stream; OutputStream *outStream = stream; StdRandomSource *randSource = new StdRandomSource(); unsigned char *bufferA = new unsigned char[10]; unsigned char *bufferB = new unsigned char[15]; int i; printf( "bufferA = \n" ); for( i=0; i<10; i++ ) { bufferA[i] = (unsigned char)( randSource->getRandomBoundedInt(0, 255) ); printf( "%d\n", bufferA[i] ); } printf( "bufferB = \n" ); for( i=0; i<15; i++ ) { bufferB[i] = (unsigned char)( randSource->getRandomBoundedInt(0, 255) ); printf( "%d\n", bufferB[i] ); } unsigned char *bufferC = new unsigned char[ 10 + 15]; outStream->write( bufferA, 10 ); outStream->write( bufferB, 15 ); inStream->read( bufferC, 10 + 10 ); char *error = inStream->getLastError(); if( error != NULL ) { printf( "Stream error %s\n", error ); delete [] error; } printf( "bufferc = \n" ); for( i=0; i<10 + 15; i++ ) { printf( "%d\n", bufferC[i] ); } inStream->read( bufferC, 10 ); error = inStream->getLastError(); if( error != NULL ) { printf( "Stream error %s\n", error ); delete [] error; } printf( "bufferc = \n" ); for( i=0; i<10 + 15; i++ ) { printf( "%d\n", bufferC[i] ); } delete [] bufferA; delete [] bufferB; delete [] bufferC; delete randSource; delete stream; } between-6+dfsg1.orig/minorGems/io/linux/0000750000175000017500000000000011435543334016753 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/io/linux/TypeIOLinux.cpp0000640000175000017500000000524511435543334021657 0ustar pabspabs/* * Modification History * * 2001-February-3 Jason Rohrer * Created. * Fixed a bug in the big-endian code. * Fixed parameter names to match convention. * * 2001-February-26 Jason Rohrer * Fixed a bug in the little-endian implementation. * * 2001-August-28 Jason Rohrer * Changed to be FreeBSD compatible. * * 2002-March-13 Jason Rohrer * Started to change to work with solaris. * Finished changing to work with solaris. * * 2002-April-11 Jason Rohrer * Added a default BSD case to work with OSX. * * 2002-May-25 Jason Rohrer * Changed to use minorGems endian.h */ #include "minorGems/io/TypeIO.h" #include "minorGems/system/endian.h" /* * Linux-specific type input and output. * Note that all types are output in the order that * a big-endian linux machine outputs them with no conversion. */ #if __BYTE_ORDER == __LITTLE_ENDIAN void TypeIO::doubleToBytes( double inDouble, unsigned char *outBytes ) { unsigned char *doubleBuffer = (unsigned char*)( &inDouble ); // output second word first outBytes[0] = doubleBuffer[7]; outBytes[1] = doubleBuffer[6]; outBytes[2] = doubleBuffer[5]; outBytes[3] = doubleBuffer[4]; outBytes[4] = doubleBuffer[3]; outBytes[5] = doubleBuffer[2]; outBytes[6] = doubleBuffer[1]; outBytes[7] = doubleBuffer[0]; } double TypeIO::bytesToDouble( unsigned char *inBytes ) { double returnValue; unsigned char *doubleBuffer = (unsigned char*)( &returnValue ); // put first word at the end of this double doubleBuffer[7] = inBytes[0]; doubleBuffer[6] = inBytes[1]; doubleBuffer[5] = inBytes[2]; doubleBuffer[4] = inBytes[3]; doubleBuffer[3] = inBytes[4]; doubleBuffer[2] = inBytes[5]; doubleBuffer[1] = inBytes[6]; doubleBuffer[0] = inBytes[7]; return returnValue; } #endif #if __BYTE_ORDER == __BIG_ENDIAN void TypeIO::doubleToBytes( double inDouble, unsigned char *outBytes ) { unsigned char *doubleBuffer = (unsigned char*)( &inDouble ); // output in stored order outBytes[0] = doubleBuffer[0]; outBytes[1] = doubleBuffer[1]; outBytes[2] = doubleBuffer[2]; outBytes[3] = doubleBuffer[3]; outBytes[4] = doubleBuffer[4]; outBytes[5] = doubleBuffer[5]; outBytes[6] = doubleBuffer[6]; outBytes[7] = doubleBuffer[7]; } double TypeIO::bytesToDouble( unsigned char *inBytes ) { double returnValue; unsigned char *doubleBuffer = (unsigned char*)( &returnValue ); // store in input order doubleBuffer[0] = inBytes[0]; doubleBuffer[1] = inBytes[1]; doubleBuffer[2] = inBytes[2]; doubleBuffer[3] = inBytes[3]; doubleBuffer[4] = inBytes[4]; doubleBuffer[5] = inBytes[5]; doubleBuffer[6] = inBytes[6]; doubleBuffer[7] = inBytes[7]; return returnValue; } #endif between-6+dfsg1.orig/minorGems/io/OutputStream.h0000640000175000017500000000716011435543334020446 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. * * 2001-January-9 Jason Rohrer * Changed the "number of bytes written" parameter and return value * to longs. * * 2001-February-3 Jason Rohrer * Added a writeDouble function to fix platform-specific double problems. * Also added a writeLong function for completeness. Implemented * these functions, making use of the new TypeIO interface. * * 2001-February-12 Jason Rohrer * Changed to subclass Stream. * * 2002-February-25 Jason Rohrer * Added a function for writing a string. * * 2002-March-31 Jason Rohrer * Made destructor virtual so it works with subclasses. * * 2004-May-9 Jason Rohrer * Added support for shorts. * * 2010-May-18 Jason Rohrer * String parameters as const to fix warnings. */ #include "minorGems/common.h" #ifndef OUTPUT_STREAM_CLASS_INCLUDED #define OUTPUT_STREAM_CLASS_INCLUDED #include "Stream.h" #include "TypeIO.h" #include /** * Interface for a byte output stream. * * @author Jason Rohrer */ class OutputStream : public Stream { public: OutputStream(); virtual ~OutputStream(); /** * Writes bytes to this stream. * * @param inBuffer the buffer of bytes to send. * @param inNumBytes the number of bytes to send. * * @return the number of bytes written successfully, * or -1 for a stream error. */ virtual long write( unsigned char *inBuffer, long inNumBytes ) = 0; /** * Writes a string to this stream. * * @param inString a \0-terminated string. * Must be destroyed by caller. * @return the number of bytes written successfully, or -1 for a * stream error. */ long writeString( const char *inString ); /** * Writes a double to the stream in a platform-independent way. * * @param inDouble the double to write * * @return the number of bytes written successfully, or -1 for a * stream error. */ long writeDouble( double inDouble ); /** * Writes a long to the stream in a platform-independent way. * * @param inLong the long to write * * @return the number of bytes written successfully, or -1 for a * stream error. */ long writeLong( long inLong ); /** * Writes a short to the stream in a platform-independent way. * * @param inShort the long to write * * @return the number of bytes written successfully, or -1 for a * stream error. */ long writeShort( short inShort ); private: unsigned char *mDoubleBuffer; unsigned char *mLongBuffer; unsigned char *mShortBuffer; }; inline OutputStream::OutputStream() : mDoubleBuffer( new unsigned char[8] ), mLongBuffer( new unsigned char[4] ), mShortBuffer( new unsigned char[2] ) { } inline OutputStream::~OutputStream() { delete [] mDoubleBuffer; delete [] mLongBuffer; delete [] mShortBuffer; } inline long OutputStream::writeString( const char *inString ) { int numBytes = write( (unsigned char *)inString, strlen( inString ) ); return numBytes; } inline long OutputStream::writeDouble( double inDouble ) { TypeIO::doubleToBytes( inDouble, mDoubleBuffer ); int numBytes = write( mDoubleBuffer, 8 ); return numBytes; } inline long OutputStream::writeLong( long inLong ) { TypeIO::longToBytes( inLong, mLongBuffer ); int numBytes = write( mLongBuffer, 4 ); return numBytes; } inline long OutputStream::writeShort( short inShort ) { TypeIO::shortToBytes( inShort, mShortBuffer ); int numBytes = write( mShortBuffer, 2 ); return numBytes; } #endif between-6+dfsg1.orig/minorGems/io/PipedStream.h0000640000175000017500000000765111435543334020214 0ustar pabspabs/* * Modification History * * 2001-February-19 Jason Rohrer * Created. * * 2001-February-20 Jason Rohrer * Added a missing return value. */ #include "minorGems/common.h" #ifndef PIPED_STREAM_CLASS_INCLUDED #define PIPED_STREAM_CLASS_INCLUDED #include "minorGems/io/InputStream.h" #include "minorGems/io/OutputStream.h" #include "minorGems/util/SimpleVector.h" #include /** * An input/output stream that can server as a pipe between * two components that read from and write to streams. * * Buffered internally to prevent blocking, so is compatible * with non-threaded components. Note, however, that * ever buffer written to the stream is copied internally, * so max memory usage is doubled. * * IS NOT THREAD-SAFE! * * @author Jason Rohrer */ class PipedStream : public InputStream, public OutputStream { public: /** * Constructs a PipedStream. */ PipedStream(); /** * Destroys any pending unread buffers. */ ~PipedStream(); // implements the InputStream interface long read( unsigned char *inBuffer, long inNumBytes ); // implements the OutputStream interface long write( unsigned char *inBuffer, long inNumBytes ); protected: SimpleVector *mBuffers; SimpleVector *mBufferSizes; long mCurrentBufferIndex; }; inline PipedStream::PipedStream() : mBuffers( new SimpleVector() ), mBufferSizes( new SimpleVector() ), mCurrentBufferIndex( 0 ) { } inline PipedStream::~PipedStream() { int numRemaining = mBuffers->size(); for( int i=0; igetElement( i ) ); delete [] buffer; } delete mBuffers; delete mBufferSizes; } inline long PipedStream::read( unsigned char *inBuffer, long inNumBytes ) { if( mBuffers->size() == 0 ) { // none read, since no buffers available InputStream:: setNewLastErrorConst( "No data available on piped stream read." ); return 0; } else { unsigned char *currentBuffer = *( mBuffers->getElement( 0 ) ); long currentBufferSize = *( mBufferSizes->getElement( 0 ) ); long outputIndex = 0; while( outputIndex < inNumBytes ) { long bytesRemaining = inNumBytes - outputIndex; long bytesRemainingInCurrent = currentBufferSize - mCurrentBufferIndex; // if current buffer isn't big enough to fill output if( bytesRemaining >= bytesRemainingInCurrent ) { // copy all of current buffer into inBuffer memcpy( &( inBuffer[outputIndex] ), &( currentBuffer[mCurrentBufferIndex] ), bytesRemainingInCurrent ); outputIndex += bytesRemainingInCurrent; // delete the current buffer mBuffers->deleteElement( 0 ); mBufferSizes->deleteElement( 0 ); delete [] currentBuffer; mCurrentBufferIndex = 0; if( outputIndex != inNumBytes && mBuffers->size() == 0 ) { // partial read, since no more buffers available InputStream::setNewLastErrorConst( "Partial data available on piped stream read." ); return outputIndex; } if( mBuffers->size() != 0 ) { // get the new current buffer currentBuffer = *( mBuffers->getElement( 0 ) ); currentBufferSize = *( mBufferSizes->getElement( 0 ) ); } } else { // current buffer is bigger memcpy( &( inBuffer[outputIndex] ), &( currentBuffer[mCurrentBufferIndex] ), bytesRemaining ); mCurrentBufferIndex += bytesRemaining; outputIndex += bytesRemaining; } } // end while // if we made it out of the while loop, we read all bytes return inNumBytes; } // end else } inline long PipedStream::write( unsigned char *inBuffer, long inNumBytes ) { // add a copy of the buffer to the vector of buffers unsigned char *copy = new unsigned char[ inNumBytes ]; memcpy( copy, inBuffer, inNumBytes ); mBuffers->push_back( copy ); mBufferSizes->push_back( inNumBytes ); return inNumBytes; } #endif between-6+dfsg1.orig/minorGems/io/Stream.h0000640000175000017500000000513711435543334017227 0ustar pabspabs/* * Modification History * * 2001-February-12 Jason Rohrer * Created. * * 2002-March-29 Jason Rohrer * Added Fortify inclusion. * * 2002-March-31 Jason Rohrer * Made destructor virtual so it works with subclasses. * Fixed several bugs in deletion of mLastError. */ #include "minorGems/common.h" #ifndef STREAM_CLASS_INCLUDED #define STREAM_CLASS_INCLUDED #include #ifdef FORTIFY #include "minorGems/util/development/fortify/fortify.h" #endif /** * Base class for all streams. * * @author Jason Rohrer */ class Stream { public: /** * Constructs a stream. */ Stream(); virtual ~Stream(); /** * Gets the last error associated with this stream. * Calling this function clears the error until * another error occurs. * * @return the last stream error in human-readable form. * Must be destroyed by caller. Returns NULL if * there is no error. Note that this string is '\0' terminated. */ char *getLastError(); protected: /** * Called by subclasses to specify a new last error. Useful * when error doesn't contain information specifiable by * a constant string. * * @param inString human-readable string representing the error. * Note that this string must be '\0' terminated. * Will be destroyed by this class. */ void setNewLastError( char *inString ); /** * Called by subclasses to specify a new last error. Useful * when the error can be described by a constant string * * @param inString human-readable constant string representing * the error. * Note that this string must be '\0' terminated. */ void setNewLastErrorConst( const char *inString ); private: // set to NULL when there is no error char *mLastError; }; inline Stream::Stream() : mLastError( NULL ) { } inline Stream::~Stream() { if( mLastError != NULL ) { delete [] mLastError; } } inline char *Stream::getLastError() { char *returnString = mLastError; mLastError = NULL; return returnString; } inline void Stream::setNewLastError( char *inString ) { if( mLastError != NULL ) { delete [] mLastError; } mLastError = inString; } inline void Stream::setNewLastErrorConst( const char *inString ) { int length = 0; char lastChar = 'a'; while( lastChar != '\0' ) { lastChar = inString[length]; length++; } // add one more to length to accommodate '\0' terminination length++; if( mLastError != NULL ) { delete [] mLastError; } mLastError = new char[ length ]; memcpy( mLastError, inString, length ); } #endif between-6+dfsg1.orig/minorGems/io/win32/0000750000175000017500000000000011435543334016556 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/io/win32/TypeIOWin32.cpp0000640000175000017500000000247111435543334021263 0ustar pabspabs/* * Modification History * * 2001-February-3 Jason Rohrer * Created. * Fixed parameter names to match convention. * * 2001-February-4 Jason Rohrer * Fixed a byte-order bug. */ #include "minorGems/io/TypeIO.h" /* * Win32-specific type input and output. * Note that all types are output in the order that * a big-endian linux machine outputs them with no conversion. */ // windows machines are all little-endian void TypeIO::doubleToBytes( double inDouble, unsigned char *outBytes ) { unsigned char *doubleBuffer = (unsigned char*)( &inDouble ); // output second word first outBytes[0] = doubleBuffer[7]; outBytes[1] = doubleBuffer[6]; outBytes[2] = doubleBuffer[5]; outBytes[3] = doubleBuffer[4]; outBytes[4] = doubleBuffer[3]; outBytes[5] = doubleBuffer[2]; outBytes[6] = doubleBuffer[1]; outBytes[7] = doubleBuffer[0]; } double TypeIO::bytesToDouble( unsigned char *inBytes ) { double returnValue; unsigned char *doubleBuffer = (unsigned char*)( &returnValue ); // put first word at the end of this double doubleBuffer[7] = inBytes[0]; doubleBuffer[6] = inBytes[1]; doubleBuffer[5] = inBytes[2]; doubleBuffer[4] = inBytes[3]; doubleBuffer[3] = inBytes[4]; doubleBuffer[2] = inBytes[5]; doubleBuffer[1] = inBytes[6]; doubleBuffer[0] = inBytes[7]; return returnValue; } between-6+dfsg1.orig/minorGems/formats/0000750000175000017500000000000011435543334016660 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/formats/xml/0000750000175000017500000000000011435543334017460 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/formats/xml/XMLUtils.cpp0000640000175000017500000000470211435543334021651 0ustar pabspabs/* * Modification History * * 2002-September-12 Jason Rohrer * Created. */ #include "XMLUtils.h" #include "minorGems/util/stringUtils.h" #include "minorGems/util/SimpleVector.h" #include char *XMLUtils::escapeDisallowedCharacters( char *inString ) { SimpleVector *returnStringVector = new SimpleVector(); int stringLength = strlen( inString ); int i; for( i=0; ipush_back( '&' ); returnStringVector->push_back( 'a' ); returnStringVector->push_back( 'm' ); returnStringVector->push_back( 'p' ); returnStringVector->push_back( ';' ); break; case '<': returnStringVector->push_back( '&' ); returnStringVector->push_back( 'l' ); returnStringVector->push_back( 't' ); returnStringVector->push_back( ';' ); break; case '>': returnStringVector->push_back( '&' ); returnStringVector->push_back( 'g' ); returnStringVector->push_back( 't' ); returnStringVector->push_back( ';' ); break; case '\"': returnStringVector->push_back( '&' ); returnStringVector->push_back( 'q' ); returnStringVector->push_back( 'u' ); returnStringVector->push_back( 'o' ); returnStringVector->push_back( 't' ); returnStringVector->push_back( ';' ); break; case '\'': returnStringVector->push_back( '&' ); returnStringVector->push_back( 'a' ); returnStringVector->push_back( 'p' ); returnStringVector->push_back( 'o' ); returnStringVector->push_back( 's' ); returnStringVector->push_back( ';' ); break; default: returnStringVector->push_back( inString[i] ); break; } } int numChars = returnStringVector->size(); char *returnString = new char[ numChars + 1 ]; for( i=0; igetElement( i ) ); } returnString[ numChars ] = '\0'; delete returnStringVector; return returnString; } between-6+dfsg1.orig/minorGems/formats/xml/XMLUtils.h0000640000175000017500000000134111435543334021312 0ustar pabspabs/* * Modification History * * 2002-September-12 Jason Rohrer * Created. */ #ifndef XML_UTILS_INCLUDED #define XML_UTILS_INCLUDED /** * Utilities for processing XML. * * @author Jason Rohrer */ class XMLUtils { public: /** * Escapes characters disallowed in XML character data. * * @param the string to escape as a \0-terminated string. * Must be destroyed by caller if non-const. * * @return string with characters escaped as a newly allocated * \0-terminated string. * Must be destroyed by caller. */ static char *escapeDisallowedCharacters( char *inString ); }; #endif between-6+dfsg1.orig/minorGems/formats/html/0000750000175000017500000000000011435543334017624 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/formats/html/HTMLUtils.cpp0000640000175000017500000000215711435543334022123 0ustar pabspabs/* * Modification History * * 2002-September-12 Jason Rohrer * Created. */ #include "HTMLUtils.h" #include "minorGems/util/stringUtils.h" #include "minorGems/util/SimpleVector.h" #include char *HTMLUtils::removeAllTags( char *inString ) { SimpleVector *returnStringVector = new SimpleVector(); int stringLength = strlen( inString ); int i = 0; while( i < stringLength ) { if( inString[i] == '<' ) { // the start of a tag // skip all until (and including) close of tag while( i < stringLength && inString[i] != '>' ) { // do nothing i++; } } else { returnStringVector->push_back( inString[i] ); } i++; } int numChars = returnStringVector->size(); char *returnString = new char[ numChars + 1 ]; for( i=0; igetElement( i ) ); } returnString[ numChars ] = '\0'; delete returnStringVector; return returnString; } between-6+dfsg1.orig/minorGems/formats/html/HTMLUtils.h0000640000175000017500000000131011435543334021556 0ustar pabspabs/* * Modification History * * 2002-September-12 Jason Rohrer * Created. */ #ifndef HTML_UTILS_INCLUDED #define HTML_UTILS_INCLUDED /** * Utilities for processing HTML. * * @author Jason Rohrer */ class HTMLUtils { public: /** * Removes all HTML tags from an HTML string. * * @param the HTML data as a \0-terminated string. * Must be destroyed by caller if non-const. * * @return data with all HTML tags removed as a newly allocated * \0-terminated string. * Must be destroyed by caller. */ static char *removeAllTags( char *inString ); }; #endif between-6+dfsg1.orig/minorGems/formats/encodingUtilsTestCompile0000750000175000017500000000021011435543334023557 0ustar pabspabsg++ -g -I../.. -o encodingUtilsTest encodingUtilsTest.cpp encodingUtils.cpp ../util/stringUtils.cpp ../util/StringBufferOutputStream.cppbetween-6+dfsg1.orig/minorGems/formats/encodingUtils.h0000640000175000017500000000423211435543334021642 0ustar pabspabs/* * Modification History * * 2003-August-22 Jason Rohrer * Created. * * 2003-September-22 Jason Rohrer * Added base64 encoding. */ #ifndef ENCODING_UTILS_INCLUDED #define ENCODING_UTILS_INCLUDED /** * A collection of functions for representing data in various encoding formats. * * @author Jason Rohrer */ /** * Encodes data as a ASCII hexidecimal string. * * @param inData the data to encode. * Must be destroyed by caller. * @param inDataLength the length of inData in bytes. * * @return a \0-terminated ASCII hexidecimal string containing * characters in the range [0-9] and [A-F]. * Will be twice as long as inData. * Must be destroyed by caller. */ char *hexEncode( unsigned char *inData, int inDataLength ); /** * Decodes raw data from an ASCII hexidecimal string. * * @param inHexString a \0-terminated hexidecimal string. * Must be destroyed by caller. * * @return an array of raw data, or NULL if decoding fails. * Will be half as long as inHexString. * Must be destroyed by caller if non-NULL. */ unsigned char *hexDecode( char *inHexString ); /** * Encodes data as a ASCII base64 string. * * @param inData the data to encode. * Must be destroyed by caller. * @param inDataLength the length of inData in bytes. * @param inBreakLines set to true to break lines every 76 characters, * or false to produce an unbroken base64 string. * * @return a \0-terminated ASCII base64 string containing * characters in the range [0-9], [A-Z], [a-z], and [+,/,=]. * Must be destroyed by caller. */ char *base64Encode( unsigned char *inData, int inDataLength, char inBreakLines = true ); /** * Decodes raw data from an ASCII base64 string. * * @param inBase64String a \0-terminated base64 string. Can optionally contain * linebreaks. * Must be destroyed by caller. * @param outDataLength pointer to where the length of the decoded data * should be returned. * * @return an array of raw data, or NULL if decoding fails. * Must be destroyed by caller if non-NULL. */ unsigned char *base64Decode( char *inBase64String, int *outDataLength ); #endif between-6+dfsg1.orig/minorGems/formats/encodingUtils.cpp0000640000175000017500000003143511435543334022202 0ustar pabspabs/* * Modification History * * 2003-August-22 Jason Rohrer * Created. * * 2003-September-22 Jason Rohrer * Added base64 encoding. * * 2004-March-21 Jason Rohrer * Fixed a variable scoping and redefinition bug pointed out by Benjamin Meyer. */ #include "encodingUtils.h" #include "minorGems/util/SimpleVector.h" #include #include char fourBitIntToHex( int inInt ) { char outChar[2]; if( inInt < 10 ) { sprintf( outChar, "%d", inInt ); } else { switch( inInt ) { case 10: outChar[0] = 'A'; break; case 11: outChar[0] = 'B'; break; case 12: outChar[0] = 'C'; break; case 13: outChar[0] = 'D'; break; case 14: outChar[0] = 'E'; break; case 15: outChar[0] = 'F'; break; default: outChar[0] = '0'; break; } } return outChar[0]; } // returns -1 if inHex is not a valid hex character int hexToFourBitInt( char inHex ) { int returnInt; switch( inHex ) { case '0': returnInt = 0; break; case '1': returnInt = 1; break; case '2': returnInt = 2; break; case '3': returnInt = 3; break; case '4': returnInt = 4; break; case '5': returnInt = 5; break; case '6': returnInt = 6; break; case '7': returnInt = 7; break; case '8': returnInt = 8; break; case '9': returnInt = 9; break; case 'A': case 'a': returnInt = 10; break; case 'B': case 'b': returnInt = 11; break; case 'C': case 'c': returnInt = 12; break; case 'D': case 'd': returnInt = 13; break; case 'E': case 'e': returnInt = 14; break; case 'F': case 'f': returnInt = 15; break; default: returnInt = -1; break; } return returnInt; } char *hexEncode( unsigned char *inData, int inDataLength ) { char *resultHexString = new char[ inDataLength * 2 + 1 ]; int hexStringIndex = 0; for( int i=0; i> 4 ); int lowBits = 0xF & ( currentByte ); resultHexString[ hexStringIndex ] = fourBitIntToHex( highBits ); hexStringIndex++; resultHexString[ hexStringIndex ] = fourBitIntToHex( lowBits ); hexStringIndex++; } resultHexString[ hexStringIndex ] = '\0'; return resultHexString; } unsigned char *hexDecode( char *inHexString ) { int hexLength = strlen( inHexString ); if( hexLength % 2 != 0 ) { // hex strings must be even in length return NULL; } int dataLength = hexLength / 2; unsigned char *rawData = new unsigned char[ dataLength ]; for( int i=0; i *encodingVector = new SimpleVector(); int numInLine = 0; // take groups of 3 data bytes and map them to 4 base64 digits for( int i=0; i> 18 ); unsigned int digitB = 0x3F & ( block >> 12 ); unsigned int digitC = 0x3F & ( block >> 6 ); unsigned int digitD = 0x3F & ( block ); encodingVector->push_back( binaryToAscii[ digitA ] ); encodingVector->push_back( binaryToAscii[ digitB ] ); encodingVector->push_back( binaryToAscii[ digitC ] ); encodingVector->push_back( binaryToAscii[ digitD ] ); numInLine += 4; if( inBreakLines && numInLine == 76 ) { // break the line encodingVector->push_back( '\r' ); encodingVector->push_back( '\n' ); numInLine = 0; } } else { // at end int numLeft = inDataLength - i; switch( numLeft ) { case 0: // no padding break; case 1: { // two digits, two pads unsigned int block = inData[i] << 16 | 0; unsigned int digitA = 0x3F & ( block >> 18 ); unsigned int digitB = 0x3F & ( block >> 12 ); encodingVector->push_back( binaryToAscii[ digitA ] ); encodingVector->push_back( binaryToAscii[ digitB ] ); encodingVector->push_back( '=' ); encodingVector->push_back( '=' ); break; } case 2: { // three digits, one pad unsigned int block = inData[i] << 16 | inData[i+1] << 8 | 0; // base64 digits, with digitA at left unsigned int digitA = 0x3F & ( block >> 18 ); unsigned int digitB = 0x3F & ( block >> 12 ); unsigned int digitC = 0x3F & ( block >> 6 ); encodingVector->push_back( binaryToAscii[ digitA ] ); encodingVector->push_back( binaryToAscii[ digitB ] ); encodingVector->push_back( binaryToAscii[ digitC ] ); encodingVector->push_back( '=' ); break; } default: break; } // done with all data i = inDataLength; } } char *returnString = encodingVector->getElementString(); delete encodingVector; return returnString; } unsigned char *base64Decode( char *inBase64String, int *outDataLength ) { SimpleVector *decodedVector = new SimpleVector(); int encodingLength = strlen( inBase64String ); SimpleVector *binaryEncodingVector = new SimpleVector(); int i; for( i=0; ipush_back( currentBinary ); } } int binaryEncodingLength = binaryEncodingVector->size(); unsigned char *binaryEncoding = binaryEncodingVector->getElementArray(); delete binaryEncodingVector; int blockCount = binaryEncodingLength / 4; if( binaryEncodingLength % 4 != 0 ) { // extra, 0-padded block blockCount += 1; } // take groups of 4 encoded digits and map them to 3 data bytes for( i=0; i> 16 ); unsigned int digitB = 0xFF & ( block >> 8 ); unsigned int digitC = 0xFF & ( block ); decodedVector->push_back( digitA ); decodedVector->push_back( digitB ); decodedVector->push_back( digitC ); } else { // at end int numLeft = binaryEncodingLength - i; switch( numLeft ) { case 0: // no padding break; case 1: { // impossible break; } case 2: { // two base64 digits, one data byte unsigned int block = binaryEncoding[i] << 18 | binaryEncoding[i+1] << 12 | 0; // data byte digits, with digitA at left unsigned int digitA = 0xFF & ( block >> 16 ); decodedVector->push_back( digitA ); break; } case 3: { // three base64 digits, two data bytes unsigned int block = binaryEncoding[i] << 18 | binaryEncoding[i+1] << 12 | binaryEncoding[i+2] << 6 | 0; // data byte digits, with digitA at left unsigned int digitA = 0xFF & ( block >> 16 ); unsigned int digitB = 0xFF & ( block >> 8 ); decodedVector->push_back( digitA ); decodedVector->push_back( digitB ); break; } default: break; } // done with all data i = binaryEncodingLength; } } delete [] binaryEncoding; *outDataLength = decodedVector->size(); unsigned char* returnData = decodedVector->getElementArray(); delete decodedVector; return returnData; } between-6+dfsg1.orig/minorGems/formats/encodingUtilsTest.cpp0000640000175000017500000000232111435543334023032 0ustar pabspabs/* * Modification History * * 2003-September-22 Jason Rohrer * Created. */ #include "encodingUtils.h" #include #include int main() { const char *dataString = "*#$&$(@KFI#*$(SDBM@#*!(@%" "*#$&$(@KFI#*$(SDBM@#*!(@%" "*#$&$(@KFI#*$(SDBM@#*!(@F" "*#$&$(@KFI#*$(SDBM@#*!(@F" "*#$&$(@KFI#*$(SDBM@#*!(@F" "*#$&$(@KFI#*$(SDBM@#*!(@%a"; printf( "base64 encoding the string: %s\n", dataString ); char *encoding = base64Encode( (unsigned char *)dataString, strlen( dataString ), true ); printf( "Encoded as:\n%s\n", encoding ); int decodedLength; unsigned char *decoding = base64Decode( encoding, &decodedLength ); char *buffer = new char[ decodedLength + 1 ]; memcpy( (void *)buffer, (void *)decoding, decodedLength ); buffer[ decodedLength ] = '\0'; printf( "Decoded as: %s\n", buffer ); if( strcmp( buffer, dataString ) == 0 ) { printf( "Test passed\n" ); } else { printf( "Test failed\n" ); } delete [] buffer; delete [] decoding; delete [] encoding; return 0; } between-6+dfsg1.orig/minorGems/util/0000750000175000017500000000000011435543340016157 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/util/development/0000750000175000017500000000000011503620617020500 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/util/development/leakTracer/0000750000175000017500000000000011435543337022564 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/util/development/leakTracer/LeakCheckAnalyze0000750000175000017500000000033111435543337025645 0ustar pabspabs#!/bin/sh CHECKER=`dirname $0`/LeakCheck" $@" ANALYZER=`dirname $0`/leak-analyze" $1 leak.out" echo "Checking with: $CHECKER" echo "" $CHECKER echo "" echo "Analyzing with: $ANALYZER" echo "" $ANALYZER 2>&1 | more between-6+dfsg1.orig/minorGems/util/development/leakTracer/leak-analyze0000750000175000017500000000636411435543337025100 0ustar pabspabs#!/usr/bin/perl # # Modification History # # 2004-January-17 Jason Rohrer # Fixed regexps to match both A-F and a-f for hex address strings. # # Erwin S. Andreasen # Henner Zeller # # Homepage: http://www.andreasen.org/LeakTracer/ # This program is Public Domain use IO::Handle; die "You must supply at least one argument.\n" unless $#ARGV >= 0; $ExeFile = shift @ARGV; $LeaksFile = $#ARGV >= 0 ? shift @ARGV : "leak.out"; open (LEAKS, $LeaksFile) or die "Could not open leaks data file $LeaksFile: $!"; if ($#ARGV >= 0) { $BreakOn = shift @ARGV; # Rest in @ARGV are program arguments } $n = $u = 0; while () { chop; next if (m/^\s*#/); # 1 2 3 4 5 6 7 #if (/^\s*L\s+(0x)?([0-9a-fA-F]+)\s+(0x)?([0-9a-fA-F]+)\s+(0x)?([0-9a-fA-F]+)\s+(\d+)/) { # Allocations, which have not been freed or deallocations which have not # been allocated. # 1 2 3 if (/^\s*L\s+(0x)?([0-9a-fA-F]+)\s+(\d+)/) { $addr="$2"; # ",$4,$6"; $u++ if not exists $Type{$addr}; $Count{$addr}++; $Size{$addr} += $3; # $7; $Type{$addr} = "Leak"; $n++; } elsif (/^\s*D\s+(0x)?([0-9a-fA-F]+)/) { $addr="$2"; # ",$4,$6"; $u++ if not exists $Type{$addr}; $Count{$addr}++; $Type{$addr} = "delete on not allocated memory"; $n++; } # allocations/deallocations with other errornous conditions # 1 2 3 4 5 elsif (/^\s*([SO])\s+(0x)?([0-9a-fA-F]+)\s+(0x)?([0-9a-fA-F]+)/) { $addrs = "$3,$5,$1"; $AllocDealloc{$addrs} = ("$1" =~ m/S/) ? "Different allocation schemes" : "This Memory was overwritten"; } } print STDERR "Gathered $n ($u unique) points of data.\n"; close (LEAKS); # Instead of using -batch, we just run things as usual. with -batch, # we quit on the first error, which we don't want. open (PIPE, "|gdb -q $ExeFile") or die "Cannot start gdb"; #open (PIPE, "|cat"); # Change set listsize 2 to something else to show more lines print PIPE "set prompt\nset complaints 1000\nset height 0\n"; # Optionally, run the program if (defined($BreakOn)) { print PIPE "break $BreakOn\n"; print PIPE "run ", join(" ", @ARGV), " \n"; } print PIPE "set listsize 2\n"; foreach (sort keys %AllocDealloc) { print PIPE "echo \\n#-- Alloc: $AllocDealloc{$_}\\nalloc here :\n"; @addrs = split(/,/,$_); print PIPE "l *0x" . (shift @addrs) . "\necho ..free here :\n"; print PIPE "set listsize 1\n"; print PIPE "l *0x" . (shift @addrs) . "\n"; } foreach (sort keys %Type) { print PIPE "echo \\n#-- $Type{$_}: counted $Count{$_}x"; if ($Size{$_} > 0) { print PIPE " / total Size: $Size{$_}"; } print PIPE "\\n\n"; @addrs = split(/,/,$_); print PIPE "set listsize 2\n"; print PIPE "l *0x" . (shift @addrs) . "\n"; #print PIPE "echo ..called from :\n"; #print PIPE "set listsize 1\n"; # gdb bails out, if it cannot find an address. #print PIPE "l *0x" . (shift @addrs) . "\necho ..called from :\n"; #print PIPE "l *0x" . (shift @addrs) . "\n"; } if (defined($BreakOn)) { print PIPE "kill\n"; } print PIPE "quit\n"; PIPE->flush(); wait(); close (PIPE); between-6+dfsg1.orig/minorGems/util/development/leakTracer/VERSION0000640000175000017500000000000411435543337023627 0ustar pabspabs2.3 between-6+dfsg1.orig/minorGems/util/development/leakTracer/LeakCheck0000750000175000017500000000064011435543337024324 0ustar pabspabs#!/bin/sh if [ $# -lt 1 ] ; then echo "Usage: $0 " exit 1 fi # this looks in the same directory, this # LeakCheck script resides; modify to your # needs: SHLIB=`dirname $0`/LeakTracer.so if [ ! -x $SHLIB ] ; then echo "$SHLIB not found" exit 1 fi if [ -z "$LEAKTRACE_FILE" ] ; then rm -f leak.out else rm -f "$LEAKTRACE_FILE" fi export LD_PRELOAD=$SHLIB exec $@ between-6+dfsg1.orig/minorGems/util/development/leakTracer/test.cc0000640000175000017500000000054111435543337024053 0ustar pabspabs/* * Modification History * * 2002-March-31 Jason Rohrer * Added test of strdup support. */ #include // Small leaky test program void foo() { int *x = new int; } int main() { char *str = strdup( "Test String" ); int *z = new int[10]; foo(); foo(); delete z; delete z; // delete value twice } between-6+dfsg1.orig/minorGems/util/development/leakTracer/README.html0000640000175000017500000002270511435543337024416 0ustar pabspabs

Table of contents

Introduction

LeakTracer is a small tool I wrote when checking a C++ program for memory
leaks. I couldn't get dmalloc to display what I wanted, and I just saw the
__builtin_return_address gcc-extension mentioned.

To use LeakTracer, run your program using the provided LeakCheck script. It
uses the LD_PRELOAD feature to "overlay" some functions on top of your
functions (no recompile needed). If your platform does not support LD_PRELOAD,
you can add the LeakTracer.o object file to the objects in your Makefile and
run your application. 

LeakTracer uses gdb to print out the exact line where the memory was allocated
and not freed - this of course means you have to free all dynamically
allocated data. LeakTracer also overrides the global operator new and operator
delete - this will give problems if you override them as well.

LeakTracer traces only new/new[] and delete calls - it does not look at
malloc/free/realloc.

Here is some example output:

Gathered 8 (8 unique) points of data.
(gdb)
Allocations: 1 / Size: 36
0x80608e6 is in NullArcableInstance::NullArcableInstance(void) (Machine.cc:40).
39      public:
40          NullArcableInstance() : ArcableInstance(new NullArcable) {}

Allocations: 1 / Size: 8
0x8055b02 is in init_types(void) (Type.cc:119).
118     void init_types() {
119         Type::Integer = new IntegerType;

Allocations: 1 / Size: 132 (new[])
0x805f4ab is in Hashtable::Hashtable(unsigned int) (ea/h/Hashtable.h:15).
14          Hashtable (uint _size = 32) : size(_size), count(0) {
15              table = new List [size];

[...]

Requirements

You need Perl5 and gdb installed to run the leak-analyzer. You need gcc -- I
currently use 2.95 but have used it with previous older versions without
problems.
You also need to run this on an architecture which supports
__builtin_return_address arguments that are greater than 0 - there may be
some problems on MIPS there. 

So far this code has been tested under Linux 2.2, x86 system, Solaris and
HP-UX.

Installation

Just type make. There is no install target; you should put LeakTracer
some place you can remember.

Since version 2.0, it is possible to preload the LeakTracer object on
architectures that support LD_PRELOAD (this is at least Linux and probably
others -- please report success/failure). This means it is much easier to use
the program: you do not need to relink your program with LeakTracer.o.

In case your platform does not support LD_PRELOAD, you can use LeakTracer in
the old pre 2.0 way: add LeakTracer.o to your object files -- at the very end
of them (also after -llibrary lines).

In any case your application must also be compiled with debugging enabled
(i.e. -g).

Running with LeakTracer

If you are using the shared object, run the LeakCheck script. This script
should stay in the directory where you install LeakCheck -- it will search for
LeakTracer.so file there and load it. E.g.:

~/src/LeakTracer/LeakCheck yourApplication

(if you put LeakTracer in ~/src/LeakTracer/)

Run your application as normal, performing tasks that you want to be traced
for memory leaks. While the application runs, LeakTracer will write data about
memory allocation to the file "leak.out" in the current directory. You can
override the location of that file by setting the LEAKTRACE_FILE environment
variable.

If you cannot use LD_PRELOAD, just run your application as normal after
relinking it. It will also produce a "leak.out" file when it finishes.

Detectable errors

LeakTracer is capable to detect the following problems with your program

  1) memory which is allocated but not freed
  2) (limited support for) overwritten memory at the end of the allocated
     block  ( reason = 1 )
  3) memory which is tried to be deleted but which is not allocated
     (either because of a garbage pointer or twice deletion)
     (reason = 2)
  4) memory which is allocated with new[] but deleted with simple delete
     and vice versa (reason = 4)

For the last three problems, LeakTracer can abort() your program if you
tell it so; the resulting core-dump allows to debug the problem. By default,
only the overwrite memory condition results in an abort of the program
because it is inherently critical. The two other conditions are not critical.
You can influence what LeakTracer does with the environment variable
   LT_ABORTREASON
which you can set to some numeric value which is the result of the
sum of the reasons you find in the parentesis in the enumeration above.
To abort on any reason, for example, you would set LT_ABORTREASON to 7.

Analyzing output

You should then run leak-analyze, since looking at the raw leak.out file will
not help you much. To run leak-analyze, you need Perl as well as gdb
installed (any version of gdb will do). For example:

leak-analyze myprog leak.out

You don't have to specify the leak.out filename if you just use the default
one. leak-analyze will run gdb on the file, sending it a number of commands
that will show the source lines with the memory leaks.

leak-analyze should show you something like this:

Gathered 2 (2 unique) points of data.

#-- Alloc: Different allocation schemes
alloc here :0x80485b7 is in main (test.cc:6).
5
6               int *wrong = new int[10];
..free here :0x80485d9 is in main (test.cc:11).
11              delete wrong;

#-- Leak: Allocations: 1 / Size: 168 
0x8048593 is in main (test.cc:3).
2       int main() {
3               int *array = new int [42] ;

#-- Leak: Allocations: 1 / Size: 4 
0x80485a5 is in main (test.cc:4).
3               int *array = new int [42] ;
4               int *foo = new int;
This means that total of two allocations happened, in two different places.

First a delete error is shown: you allocated some memory using new[] but you
freed it using delete. leak-analyze will show where you allocated the memory and where you freed it.

Afterwards each allocation is shown in turn. There was 1 allocation from this
line of code (test.cc:3), and it was 168 bytes in size. Note that of the two
lines of code shown, it's the bottom one that created the allocation.

That's all there is to it - now you should find those memory leaks, fix them
and rerun Leak tracer.

Shared libraries and objects

If you want to analyze the leaks in shared libraries in your file, it may be
necessary to make leak-analyze run your program and thus load the shared
libraries before searching for addresses.

To do that, run leak-analyze with the program name, leak name AND another
argument which is where to set the breakpoint, e.g.:

leak-analyze myprog leak.out main

This will make leak-analyze tell gdb to set a breakpoint on "main" and then
run the program. After the analysis is complete, the program will be killed.

If you want to load some shared libraries, you can set a breakpoint on a
different location, e.g. main.cc:42 if you know that once line 42 is reached,
all shared objects have been loaded.

If your program needs some command line arguments, supply them after "main".

Licensing

LeakTracer is public domain (i.e. do with it whatever you feel like).

Credits

Initial version of LeakTracer was written by Erwin Andreasen. Henner Zeller
(foobar@to.com) contributed a rewrite of the code which
introduced dynamic loading of LeakTracer and more.

Revision history

February 21, 1999       v1.0 - only tested internally
February 23, 1999       v1.1 - added operator new[] / delete[]
February 23, 1999           v1.2 - Oops, forgot to free() the memory..
February 26, 1999       v1.3 - allow delete 0
March 27, 1999          v1.4 - Allow %p format without leading 0x for non-GNU 
                                       libc. Option to leak-analyze to run the program.
July 21, 1999               v1.5 - Fix for the above suggested by Alan Gonzalez
August 21, 2000         v1.6 - use a destructor instead of 
                                       __attribute__(destructor)
November 19, 2000               v2.0 - Rewrite by Henner Zeller introduces LD_PRELOAD
                                       and much more
February 27, 2001               v2.1 - Further update by Henner: optional thread safety,
                                       choose what should make LeakTracer abort(), better
                                       tracing of delete on non-new'ed pointers
March 2, 2001                   v2.2 - Another updated by Henner: hash table to increase
                                       performance with many allocations
June 13, 2001                   v2.3 - Made LT more resistant to being called before init
                                       and after destruction

Authors:    Erwin Andreasen 
        Henner Zeller 
Homepage:   http://www.andreasen.org/LeakTracer/

between-6+dfsg1.orig/minorGems/util/development/leakTracer/Makefile0000640000175000017500000000262511435543337024232 0ustar pabspabs# # Modification History # # 2004-January-16 Jason Rohrer # Switched to use minorGems platform-independed mutexes. # CC = g++ # Source files SRC := LeakTracer.cc ROOT_PATH = ../../../.. # Switch comment to select a platform # PLATFORM_MUTEX = $(ROOT_PATH)/minorGems/system/win32/MutexLockWin32.cpp PLATFORM_MUTEX = $(ROOT_PATH)/minorGems/system/linux/MutexLockLinux.cpp -pthread # Comment both of these out to disable thread safetly C_THREAD=-DTHREAD_SAVE -D_REENTRANT -D_THREAD_SAFE O_THREAD = $(PLATFORM_MUTEX) # Common flags C_FLAGS = -g -pipe -Wall -W -I$(ROOT_PATH) $(C_THREAD) O_FLAGS = $(C_FLAGS) $(O_THREAD) # Object files OBJ_DIR = . OBJ := $(patsubst %.cc,$(OBJ_DIR)/%.o,$(SRC)) SHOBJ := $(patsubst %.o,$(OBJ_DIR)/%.so,$(OBJ)) .PHONY: all clean tidy distrib test all: $(OBJ) $(SHOBJ) clean: tidy rm -f $(OBJ) leak.out tidy: rm -f *~ *orig *bak *rej tags: $(SRC) $(INCL) ctags $(SRC) $(INCL) distrib: clean all README.html (cd .. && tar cvfz /root/drylock/LeakTracer/LeakTracer.tar.gz --exclude LeakTracer/CVS --exclude LeakTracer/old --exclude LeakTracer/test LeakTracer/) $(OBJ_DIR)/%.o: %.cc $(CC) -fPIC -c $(C_FLAGS) $< -o $@ $(OBJ_DIR)/%.so : $(OBJ_DIR)/%.o $(CC) $(O_FLAGS) -shared -o $@ $< README.html: README /root/ed/mcl/util/htmlize.pl README test: $(CC) $(C_FLAGS) test.cc -o test ./test ./LeakCheck ./test ./leak-analyze ./test # ./compare-test test.template test.result between-6+dfsg1.orig/minorGems/util/development/leakTracer/README0000640000175000017500000002130111435543337023442 0ustar pabspabsIntroduction ------------ LeakTracer is a small tool I wrote when checking a C++ program for memory leaks. I couldn't get dmalloc to display what I wanted, and I just saw the __builtin_return_address gcc-extension mentioned. To use LeakTracer, run your program using the provided LeakCheck script. It uses the LD_PRELOAD feature to "overlay" some functions on top of your functions (no recompile needed). If your platform does not support LD_PRELOAD, you can add the LeakTracer.o object file to the objects in your Makefile and run your application. LeakTracer uses gdb to print out the exact line where the memory was allocated and not freed - this of course means you have to free all dynamically allocated data. LeakTracer also overrides the global operator new and operator delete - this will give problems if you override them as well. LeakTracer traces only new/new[] and delete calls - it does not look at malloc/free/realloc. Here is some example output: Gathered 8 (8 unique) points of data. (gdb) Allocations: 1 / Size: 36 0x80608e6 is in NullArcableInstance::NullArcableInstance(void) (Machine.cc:40). 39 public: 40 NullArcableInstance() : ArcableInstance(new NullArcable) {} Allocations: 1 / Size: 8 0x8055b02 is in init_types(void) (Type.cc:119). 118 void init_types() { 119 Type::Integer = new IntegerType; Allocations: 1 / Size: 132 (new[]) 0x805f4ab is in Hashtable::Hashtable(unsigned int) (ea/h/Hashtable.h:15). 14 Hashtable (uint _size = 32) : size(_size), count(0) { 15 table = new List [size]; [...] Requirements ------------ You need Perl5 and gdb installed to run the leak-analyzer. You need gcc -- I currently use 2.95 but have used it with previous older versions without problems. You also need to run this on an architecture which supports __builtin_return_address arguments that are greater than 0 - there may be some problems on MIPS there. So far this code has been tested under Linux 2.2, x86 system, Solaris and HP-UX. Installation ------------ Just type make. There is no install target; you should put LeakTracer some place you can remember. Since version 2.0, it is possible to preload the LeakTracer object on architectures that support LD_PRELOAD (this is at least Linux and probably others -- please report success/failure). This means it is much easier to use the program: you do not need to relink your program with LeakTracer.o. In case your platform does not support LD_PRELOAD, you can use LeakTracer in the old pre 2.0 way: add LeakTracer.o to your object files -- at the very end of them (also after -llibrary lines). In any case your application must also be compiled with debugging enabled (i.e. -g). Running with LeakTracer ----------------------- If you are using the shared object, run the LeakCheck script. This script should stay in the directory where you install LeakCheck -- it will search for LeakTracer.so file there and load it. E.g.: ~/src/LeakTracer/LeakCheck yourApplication (if you put LeakTracer in ~/src/LeakTracer/) Run your application as normal, performing tasks that you want to be traced for memory leaks. While the application runs, LeakTracer will write data about memory allocation to the file "leak.out" in the current directory. You can override the location of that file by setting the LEAKTRACE_FILE environment variable. If you cannot use LD_PRELOAD, just run your application as normal after relinking it. It will also produce a "leak.out" file when it finishes. Detectable errors ----------------- LeakTracer is capable to detect the following problems with your program 1) memory which is allocated but not freed 2) (limited support for) overwritten memory at the end of the allocated block ( reason = 1 ) 3) memory which is tried to be deleted but which is not allocated (either because of a garbage pointer or twice deletion) (reason = 2) 4) memory which is allocated with new[] but deleted with simple delete and vice versa (reason = 4) For the last three problems, LeakTracer can abort() your program if you tell it so; the resulting core-dump allows to debug the problem. By default, only the overwrite memory condition results in an abort of the program because it is inherently critical. The two other conditions are not critical. You can influence what LeakTracer does with the environment variable LT_ABORTREASON which you can set to some numeric value which is the result of the sum of the reasons you find in the parentesis in the enumeration above. To abort on any reason, for example, you would set LT_ABORTREASON to 7. Analyzing output ---------------- You should then run leak-analyze, since looking at the raw leak.out file will not help you much. To run leak-analyze, you need Perl as well as gdb installed (any version of gdb will do). For example: leak-analyze myprog leak.out You don't have to specify the leak.out filename if you just use the default one. leak-analyze will run gdb on the file, sending it a number of commands that will show the source lines with the memory leaks. leak-analyze should show you something like this: Gathered 2 (2 unique) points of data. #-- Alloc: Different allocation schemes alloc here :0x80485b7 is in main (test.cc:6). 5 6 int *wrong = new int[10]; ..free here :0x80485d9 is in main (test.cc:11). 11 delete wrong; #-- Leak: Allocations: 1 / Size: 168 0x8048593 is in main (test.cc:3). 2 int main() { 3 int *array = new int [42] ; #-- Leak: Allocations: 1 / Size: 4 0x80485a5 is in main (test.cc:4). 3 int *array = new int [42] ; 4 int *foo = new int; This means that total of two allocations happened, in two different places. First a delete error is shown: you allocated some memory using new[] but you freed it using delete. leak-analyze will show where you allocated the memory and where you freed it. Afterwards each allocation is shown in turn. There was 1 allocation from this line of code (test.cc:3), and it was 168 bytes in size. Note that of the two lines of code shown, it's the bottom one that created the allocation. That's all there is to it - now you should find those memory leaks, fix them and rerun Leak tracer. Shared libraries and objects ---------------------------- If you want to analyze the leaks in shared libraries in your file, it may be necessary to make leak-analyze run your program and thus load the shared libraries before searching for addresses. To do that, run leak-analyze with the program name, leak name AND another argument which is where to set the breakpoint, e.g.: leak-analyze myprog leak.out main This will make leak-analyze tell gdb to set a breakpoint on "main" and then run the program. After the analysis is complete, the program will be killed. If you want to load some shared libraries, you can set a breakpoint on a different location, e.g. main.cc:42 if you know that once line 42 is reached, all shared objects have been loaded. If your program needs some command line arguments, supply them after "main". Licensing --------- LeakTracer is public domain (i.e. do with it whatever you feel like). Credits ------- Initial version of LeakTracer was written by Erwin Andreasen. Henner Zeller (foobar@to.com) contributed a rewrite of the code which introduced dynamic loading of LeakTracer and more. Revision history ---------------- February 21, 1999 v1.0 - only tested internally February 23, 1999 v1.1 - added operator new[] / delete[] February 23, 1999 v1.2 - Oops, forgot to free() the memory.. February 26, 1999 v1.3 - allow delete 0 March 27, 1999 v1.4 - Allow %p format without leading 0x for non-GNU libc. Option to leak-analyze to run the program. July 21, 1999 v1.5 - Fix for the above suggested by Alan Gonzalez August 21, 2000 v1.6 - use a destructor instead of __attribute__(destructor) November 19, 2000 v2.0 - Rewrite by Henner Zeller introduces LD_PRELOAD and much more February 27, 2001 v2.1 - Further update by Henner: optional thread safety, choose what should make LeakTracer abort(), better tracing of delete on non-new'ed pointers March 2, 2001 v2.2 - Another updated by Henner: hash table to increase performance with many allocations June 13, 2001 v2.3 - Made LT more resistant to being called before init and after destruction Authors: Erwin Andreasen Henner Zeller Homepage: http://www.andreasen.org/LeakTracer/ between-6+dfsg1.orig/minorGems/util/development/leakTracer/LeakTracer.cc0000640000175000017500000003332011435543337025112 0ustar pabspabs/* * Modification History * * 2002-March-31 Jason Rohrer * Added support for strdup. * Fixed bug in strdup. * * 2003-October-3 Jason Rohrer * Added printout of leak contents in report. * * 2004-January-16 Jason Rohrer * Switched to use minorGems platform-independed mutexes. * Changed to use simpler fopen call to open report. */ /* * Homepage: * * Authors: * Erwin S. Andreasen * Henner Zeller * * This program is Public Domain */ #ifdef THREAD_SAVE #define _THREAD_SAVE //#include #include "minorGems/system/MutexLock.h" #endif #include #include #include #include #include #include #include #include #include #include /* * underlying allocation, de-allocation used within * this tool */ #define LT_MALLOC malloc #define LT_FREE free #define LT_REALLOC realloc /* * prime number for the address lookup hash table. * if you have _really_ many memory allocations, use a * higher value, like 343051 for instance. */ #define SOME_PRIME 35323 #define ADDR_HASH(addr) ((unsigned long) addr % SOME_PRIME) /** * Filedescriptor to write to. This should not be a low number, * because these often have special meanings (stdin, out, err) * and may be closed by the program (daemons) * So choose an arbitrary higher FileDescriptor .. e.g. 42 */ #define FILEDESC 42 /** * allocate a bit more memory in order to check if there is a memory * overwrite. Either 0 or more than sizeof(unsigned int). Note, you can * only detect memory over_write_, not _reading_ beyond the boundaries. Better * use electric fence for these kind of bugs * */ typedef unsigned long magic_t; #define MAGIC ((magic_t) 0xAABBCCDDLu) /** * this may be more than sizeof(magic_t); if you want more, then * sepecify it like #define SAVESIZE (sizeof(magic_t) + 12) */ #define SAVESIZE (sizeof(magic_t) + 0) /** * on 'new', initialize the memory with this value. * if not defined - uninitialized. This is very helpful because * it detects if you initialize your classes correctly .. if not, * this helps you faster to get the segmentation fault you're * implicitly asking for :-). * * Set this to some value which is likely to produce a * segmentation fault on your platform. */ #define SAVEVALUE 0xAA /** * on 'delete', clean memory with this value. * if not defined - no memory clean. * * Set this to some value which is likely to produce a * segmentation fault on your platform. */ #define MEMCLEAN 0xEE /** * Initial Number of memory allocations in our list. * Doubles for each re-allocation. */ #define INITIALSIZE 32768 static class LeakTracer { struct Leak { const void *addr; size_t size; const void *allocAddr; bool type; int nextBucket; }; int newCount; // how many memory blocks do we have int leaksCount; // amount of entries in the leaks array int firstFreeSpot; // Where is the first free spot in the leaks array? int currentAllocated; // currentAllocatedMemory int maxAllocated; // maximum Allocated unsigned long totalAllocations; // total number of allocations. stats. unsigned int abortOn; // resons to abort program (see abortReason_t) /** * Have we been initialized yet? We depend on this being * false before constructor has been called! */ bool initialized; bool destroyed; // Has our destructor been called? FILE *report; // filedescriptor to write to /** * pre-allocated array of leak info structs. */ Leak *leaks; /** * fast hash to lookup the spot where an allocation is * stored in case of an delete. map */ int *leakHash; // fast lookup #ifdef THREAD_SAVE MutexLock mutex; #endif enum abortReason_t { OVERWRITE_MEMORY = 0x01, DELETE_NONEXISTENT = 0x02, NEW_DELETE_MISMATCH = 0x04 }; public: LeakTracer() { initialize(); } void initialize() { // Unfortunately we might be called before our constructor has actualy fired if (initialized) return; // fprintf(stderr, "LeakTracer::initialize()\n"); initialized = true; newCount = 0; leaksCount = 0; firstFreeSpot = 1; // index '0' is special currentAllocated = 0; maxAllocated = 0; totalAllocations = 0; abortOn = OVERWRITE_MEMORY; // only _severe_ reason report = 0; leaks = 0; leakHash = 0; char uniqFilename[256]; const char *filename = getenv("LEAKTRACE_FILE") ? : "leak.out"; struct stat dummy; if (stat(filename, &dummy) == 0) { sprintf(uniqFilename, "%s.%d", filename, getpid()); fprintf(stderr, "LeakTracer: file exists; using %s instead\n", uniqFilename); } else { sprintf(uniqFilename, "%s", filename); } // not sure why this "open" code is here // (it doesn't open the file properly in MinGW on win32) /* int reportfd = open(uniqFilename, O_WRONLY|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE); if (reportfd < 0) { fprintf(stderr, "LeakTracer: cannot open %s: %m\n", filename); report = stderr; } else { int dupfd = dup2(reportfd, FILEDESC); close(reportfd); report = fdopen(dupfd, "w"); if (report == NULL) { report = stderr; } } */ // simpler version using only fopen report = fopen( uniqFilename, "w" ); if( report == NULL ) { fprintf( stderr, "LeakTracer: cannot open %s\n", uniqFilename ); report = stderr; } time_t t = time(NULL); fprintf (report, "# starting %s", ctime(&t)); leakHash = (int*) LT_MALLOC(SOME_PRIME * sizeof(int)); memset ((void*) leakHash, 0x00, SOME_PRIME * sizeof(int)); #ifdef MAGIC fprintf (report, "# memory overrun protection of %d Bytes " "with magic 0x%4lX\n", SAVESIZE, MAGIC); #endif #ifdef SAVEVALUE fprintf (report, "# initializing new memory with 0x%2X\n", SAVEVALUE); #endif #ifdef MEMCLEAN fprintf (report, "# sweeping deleted memory with 0x%2X\n", MEMCLEAN); #endif if (getenv("LT_ABORTREASON")) { abortOn = atoi(getenv("LT_ABORTREASON")); } #define PRINTREASON(x) if (abortOn & x) fprintf(report, "%s ", #x); fprintf (report, "# aborts on "); PRINTREASON( OVERWRITE_MEMORY ); PRINTREASON( DELETE_NONEXISTENT ); PRINTREASON( NEW_DELETE_MISMATCH ); fprintf (report, "\n"); #undef PRINTREASON #ifdef THREAD_SAVE fprintf (report, "# thread save\n"); /* * create default, non-recursive ('fast') mutex * to lock our datastructure where we keep track of * the user's new/deletes */ /*if (pthread_mutex_init(&mutex, NULL) < 0) { fprintf(report, "# couldn't init mutex ..\n"); fclose(report); _exit(1); }*/ #else fprintf(report, "# not thread save; if you use threads, recompile with -DTHREAD_SAVE\n"); #endif fflush(report); } /* * the workhorses: */ void *registerAlloc(size_t size, bool type); void registerFree (void *p, bool type); /** * write a hexdump of the given area. */ void hexdump(const unsigned char* area, int size); /** * Terminate current running progam. */ void progAbort(abortReason_t reason) { if (abortOn & reason) { fprintf(report, "# abort; DUMP of current state\n"); writeLeakReport(); fclose(report); abort(); } else fflush(report); } /** * write a Report over leaks, e.g. still pending deletes */ void writeLeakReport(); ~LeakTracer() { // fprintf(stderr, "LeakTracer::destroy()\n"); time_t t = time(NULL); fprintf (report, "# finished %s", ctime(&t)); writeLeakReport(); fclose(report); free(leaks); #ifdef THREAD_SAVE //pthread_mutex_destroy(&mutex); #endif destroyed = true; } } leakTracer; void* LeakTracer::registerAlloc (size_t size, bool type) { initialize(); // fprintf(stderr, "LeakTracer::registerAlloc()\n"); if (destroyed) { fprintf(stderr, "Oops, registerAlloc called after destruction of LeakTracer (size=%d)\n", size); return LT_MALLOC(size); } void *p = LT_MALLOC(size + SAVESIZE); // Need to call the new-handler if (!p) { fprintf(report, "LeakTracer malloc %m\n"); _exit (1); } #ifdef SAVEVALUE /* initialize with some defined pattern */ memset(p, SAVEVALUE, size + SAVESIZE); #endif #ifdef MAGIC /* * the magic value is a special pattern which does not need * to be uniform. */ if (SAVESIZE >= sizeof(magic_t)) { magic_t *mag; mag = (magic_t*)((char*)p + size); *mag = MAGIC; } #endif #ifdef THREAD_SAVE //pthread_mutex_lock(&mutex); mutex.lock(); #endif ++newCount; ++totalAllocations; currentAllocated += size; if (currentAllocated > maxAllocated) maxAllocated = currentAllocated; for (;;) { for (int i = firstFreeSpot; i < leaksCount; i++) if (leaks[i].addr == NULL) { leaks[i].addr = p; leaks[i].size = size; leaks[i].type = type; leaks[i].allocAddr=__builtin_return_address(1); firstFreeSpot = i+1; // allow to lookup our index fast. int *hashPos = &leakHash[ ADDR_HASH(p) ]; leaks[i].nextBucket = *hashPos; *hashPos = i; #ifdef THREAD_SAVE //pthread_mutex_unlock(&mutex); mutex.unlock(); #endif return p; } // Allocate a bigger array // Note that leaksCount starts out at 0. int new_leaksCount = (leaksCount == 0) ? INITIALSIZE : leaksCount * 2; leaks = (Leak*)LT_REALLOC(leaks, sizeof(Leak) * new_leaksCount); if (!leaks) { fprintf(report, "# LeakTracer realloc failed: %m\n"); _exit(1); } else { fprintf(report, "# internal buffer now %d\n", new_leaksCount); fflush(report); } memset(leaks+leaksCount, 0x00, sizeof(Leak) * (new_leaksCount-leaksCount)); leaksCount = new_leaksCount; } } void LeakTracer::hexdump(const unsigned char* area, int size) { fprintf(report, "# "); for (int j=0; j < size ; ++j) { fprintf (report, "%02x ", *(area+j)); if (j % 16 == 15) { fprintf(report, " "); for (int k=-15; k < 0 ; k++) { char c = (char) *(area + j + k); fprintf (report, "%c", isprint(c) ? c : '.'); } fprintf(report, "\n# "); } } fprintf(report, "\n"); } void LeakTracer::registerFree (void *p, bool type) { initialize(); if (p == NULL) return; if (destroyed) { fprintf(stderr, "Oops, allocation destruction of LeakTracer (p=%p)\n", p); return; } #ifdef THREAD_SAVE //pthread_mutex_lock(&mutex); mutex.lock(); #endif int *lastPointer = &leakHash[ ADDR_HASH(p) ]; int i = *lastPointer; while (i != 0 && leaks[i].addr != p) { lastPointer = &leaks[i].nextBucket; i = *lastPointer; } if (leaks[i].addr == p) { *lastPointer = leaks[i].nextBucket; // detach. newCount--; leaks[i].addr = NULL; currentAllocated -= leaks[i].size; if (i < firstFreeSpot) firstFreeSpot = i; if (leaks[i].type != type) { fprintf(report, "S %10p %10p # new%s but delete%s " "; size %d\n", leaks[i].allocAddr, __builtin_return_address(1), ((!type) ? "[]" : " normal"), ((type) ? "[]" : " normal"), leaks[i].size); progAbort( NEW_DELETE_MISMATCH ); } #ifdef MAGIC if ((SAVESIZE >= sizeof(magic_t)) && *((magic_t*)((char*)p + leaks[i].size)) != MAGIC) { fprintf(report, "O %10p %10p " "# memory overwritten beyond allocated" " %d bytes\n", leaks[i].allocAddr, __builtin_return_address(1), leaks[i].size); fprintf(report, "# %d byte beyond area:\n", SAVESIZE); hexdump((unsigned char*)p+leaks[i].size, SAVESIZE); progAbort( OVERWRITE_MEMORY ); } #endif #ifdef THREAD_SAVE # ifdef MEMCLEAN int allocationSize = leaks[i].size; # endif //pthread_mutex_unlock(&mutex); mutex.unlock(); #else #define allocationSize leaks[i].size #endif #ifdef MEMCLEAN // set it to some garbage value. memset((unsigned char*)p, MEMCLEAN, allocationSize + SAVESIZE); #endif LT_FREE(p); return; } #ifdef THREAD_SAVE //pthread_mutex_unlock(&mutex); mutex.unlock(); #endif fprintf(report, "D %10p # delete non alloc or twice pointer %10p\n", __builtin_return_address(1), p); progAbort( DELETE_NONEXISTENT ); } void LeakTracer::writeLeakReport() { initialize(); if (newCount > 0) { fprintf(report, "# LeakReport\n"); fprintf(report, "# %10s | %9s # Pointer Addr\n", "from new @", "size"); } for (int i = 0; i < leaksCount; i++) if (leaks[i].addr != NULL) { // This ought to be 64-bit safe? char *memContents = (char *)LT_MALLOC( leaks[i].size + 1 ); memcpy( (void *)memContents, (void *)( leaks[i].addr ), leaks[i].size ); memContents[ leaks[i].size ] = '\0'; fprintf(report, "L %10p %9ld # %p \"%s\"\n", leaks[i].allocAddr, (long) leaks[i].size, leaks[i].addr, memContents ); LT_FREE( memContents ); } fprintf(report, "# total allocation requests: %6ld ; max. mem used" " %d kBytes\n", totalAllocations, maxAllocated / 1024); fprintf(report, "# leak %6d Bytes\t:-%c\n", currentAllocated, (currentAllocated == 0) ? ')' : '('); if (currentAllocated > 50 * 1024) { fprintf(report, "# .. that is %d kByte!! A lot ..\n", currentAllocated / 1024); } } /** -- The actual new/delete operators -- **/ void* operator new(size_t size) { return leakTracer.registerAlloc(size,false); } void* operator new[] (size_t size) { return leakTracer.registerAlloc(size,true); } void operator delete (void *p) { leakTracer.registerFree(p,false); } void operator delete[] (void *p) { leakTracer.registerFree(p,true); } // added by Jason Rohrer char *strdup( const char *inString ) { char *outString = (char*)leakTracer.registerAlloc( strlen( inString ) + 1, true ); strcpy( outString, inString ); return outString; } /* Emacs: * Local variables: * c-basic-offset: 8 * End: * vi:set tabstop=8 shiftwidth=8 nowrap: */ between-6+dfsg1.orig/minorGems/util/development/memory/0000750000175000017500000000000011435543337022017 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/util/development/memory/debugMemory.cpp0000640000175000017500000000421311435543337025003 0ustar pabspabs/* * Modification History * * 2002-October-17 Jason Rohrer * Created. * * 2002-October-18 Jason Rohrer * Added static initialization counting class for MemoryTrack. * * 2002-October-19 Jason Rohrer * Added more detail to error message. * Improved printing behavior. * Moved include of debugMemory.h to work better with IDE compilers. * Fixed to deal with differences between malloc and new[] on some platforms. * * 2002-October-20 Jason Rohrer * Removed delete macro trick that was causing crashes in tinyxml. * Removed function that was no longer being used. */ #include "minorGems/util/development/memory/debugMemory.h" #ifdef DEBUG_MEMORY #include "minorGems/util/development/memory/MemoryTrack.h" #include "stdlib.h" #include "stdio.h" void *debugMemoryNew( unsigned int inSize, const char *inFileName, int inLine ) { void *allocatedPointer = (void *)malloc( inSize ); MemoryTrack::addAllocation( allocatedPointer, inSize, SINGLE_ALLOCATION, inFileName, inLine ); return allocatedPointer; } void *debugMemoryNewArray( unsigned int inSize, const char *inFileName, int inLine ) { unsigned int mallocSize = inSize; if( inSize == 0 ) { // always allocate at least one byte to circumvent differences // between malloc and new[] on some platforms // (new int[0] returns a pointer to an array of length 0, while // malloc( 0 ) can return NULL on some platforms) mallocSize = 1; } void *allocatedPointer = (void *)malloc( mallocSize ); MemoryTrack::addAllocation( allocatedPointer, inSize, ARRAY_ALLOCATION, inFileName, inLine ); return allocatedPointer; } void debugMemoryDelete( void *inPointer ) { MemoryTrack::addDeallocation( inPointer, SINGLE_ALLOCATION ); free( inPointer ); } void debugMemoryDeleteArray( void *inPointer ) { MemoryTrack::addDeallocation( inPointer, ARRAY_ALLOCATION ); free( inPointer ); } #endif between-6+dfsg1.orig/minorGems/util/development/memory/MemoryTrack.cpp0000640000175000017500000001620511435543337024765 0ustar pabspabs/* * Modification History * * 2002-October-17 Jason Rohrer * Created. * * 2002-October-18 Jason Rohrer * Changed to use custom list instead of SimpleVector because SimpleVector * uses debugMemory. * Added static initialization counting class. * Changed to use struct and malloc for AllocationList to avoid * circular new and delete calls. * * 2002-October-19 Jason Rohrer * Fixed a bug in adding to the alloc list. * Improved printing behavior. * Added support for clearing memory on allocation and deallocation. * Fixed to ignore deallocation of our own static lock. * Fixed bug in allocation count. * Added message for NULL pointer deallocation. * Put locks in place around print statements, which are not atomic on win32. * Changed to use hex notation when printing pointers. * * 2002-October-19 Jason Rohrer * Added ifdef for DEBUG_MEMORY. * * 2002-October-20 Jason Rohrer * Removed file and line arguments from deallocation calls. */ #ifdef DEBUG_MEMORY #include "minorGems/util/development/memory/MemoryTrack.h" #include #include #include int MemoryTrackStaticInitCounter::mCount = 0; MutexLock *MemoryTrack::mLock; AllocationList *MemoryTrack::mListHead; char MemoryTrack::mTracking = false; int MemoryTrack::mTotalAllocationSize = 0; int MemoryTrack::mTotalDeallocationSize = 0; int MemoryTrack::mNumberOfAllocations = 0; void MemoryTrack::addAllocation( void *inPointer, unsigned int inAllocationSize, int inAllocationType, const char *inFileName, int inLineNumber ) { mLock->lock(); if( !mTracking ) { printf( "Tracking off on allocation (0x%x) [%d bytes] %s:%d.\n", (unsigned int)inPointer, inAllocationSize, inFileName, inLineNumber ); mLock->unlock(); return; } // insert after head of list AllocationList *element = (AllocationList *)malloc( sizeof( AllocationList ) ); element->mPrevious = (void *)mListHead; element->mNext = mListHead->mNext; mListHead->mNext = (void *)element; AllocationList *nextElement = (AllocationList *)( element->mNext ); if( nextElement != NULL ) { nextElement->mPrevious = (void *)element; } element->mPointer = inPointer; element->mAllocationSize = inAllocationSize; element->mAllocationType = inAllocationType; element->mFileName = inFileName; element->mLineNumber = inLineNumber; mTotalAllocationSize += inAllocationSize; mNumberOfAllocations ++; // wipe this block of memory clearMemory( inPointer, inAllocationSize ); mLock->unlock(); } int MemoryTrack::addDeallocation( void *inPointer, int inDeallocationType ) { mLock->lock(); if( inPointer == NULL ) { printf( "NULL pointer (0x%x) deallocated\n", (unsigned int)inPointer ); } if( inPointer == (void *)mLock ) { // we're seeing the deallocation of our own static lock as // the system exits // ignore it mLock->unlock(); return 0; } if( !mTracking ) { printf( "Tracking off on deallocation (0x%x)\n", (unsigned int)inPointer ); mLock->unlock(); return 0; } AllocationList *element = (AllocationList *)( mListHead->mNext ); while( element != NULL ) { void *pointer = element->mPointer; if( pointer == inPointer ) { unsigned int allocationSize = element->mAllocationSize; int allocationType = element->mAllocationType; const char *allocFileName = element->mFileName; int allocLineNumber = element->mLineNumber; // remove from list, whether or not types match AllocationList *previousElement = (AllocationList *)( element->mPrevious ); AllocationList *nextElement = (AllocationList *)( element->mNext ); // patch list previousElement->mNext = (void *)( nextElement ); if( nextElement != NULL ) { nextElement->mPrevious = (void *)( previousElement ); } free( element ); mTotalDeallocationSize += allocationSize; if( allocationType == inDeallocationType ) { // found and types match mLock->unlock(); // wipe this block of memory clearMemory( inPointer, allocationSize ); return 0; } else { // allocation types don't match printf( "Attempt to deallocate (0x%x) [%d bytes] with wrong" " delete form\n" " %s:%d (location of original allocation)\n", (unsigned int)inPointer, allocationSize, allocFileName, allocLineNumber ); mLock->unlock(); return 2; } } element = (AllocationList *)( element->mNext ); } // not found (delete of unallocated memory) printf( "Attempt to deallocate (0x%x) unallocated memory\n", (unsigned int)inPointer ); mLock->unlock(); return 1; } void MemoryTrack::printLeaks() { mLock->lock(); printf( "\n\n---- debugMemory report ----\n" ); printf( "Number of Allocations: %d\n", mNumberOfAllocations ); printf( "Total allocations: %d bytes\n", mTotalAllocationSize ); printf( "Total deallocations: %d bytes\n", mTotalDeallocationSize ); int leakEstimate = mTotalAllocationSize - mTotalDeallocationSize; AllocationList *element = (AllocationList *)( mListHead->mNext ); if( element == NULL ) { printf( "No leaks detected.\n" ); } else { printf( "Leaks detected:\n" ); } int leakSum = 0; while( element != NULL ) { printf( "Not deallocated (0x%x) [%d bytes]\n" " %s:%d (location of original allocation)\n", (unsigned int)( element->mPointer ), element->mAllocationSize, element->mFileName, element->mLineNumber ); leakSum += element->mAllocationSize; element = (AllocationList *)( element->mNext ); } if( leakSum != leakEstimate ) { printf( "Warning: Leak sum does not equal leak estimate.\n" ); } printf( "Leaked memory: %d bytes\n", leakSum ); printf( "---- END debugMemory report ----\n\n" ); mLock->unlock(); } void MemoryTrack::clearMemory( void *inPointer, unsigned int inSize ) { unsigned char *charArray = (unsigned char *)inPointer; for( unsigned int i=0; i #include #define SINGLE_ALLOCATION 0 #define ARRAY_ALLOCATION 1 /** * Linked list of memory allocations. * * @author Jason Rohrer */ typedef struct { void *mPrevious; void *mNext; void *mPointer; unsigned int mAllocationSize; int mAllocationType; const char *mFileName; int mLineNumber; } AllocationList; /** * Class that tracks memory allocations and deallocations. * * @author Jason Rohrer */ class MemoryTrack { public: /** * Adds an allocation to this tracker and clears the allocated * memory block. * * @param inPointer a pointer to the allocated memory. * @param inAllocationType the type of allocation, * either SINGLE_ALLOCATION or ARRAY_ALLOCATION. * @param inAllocationSize the size of the allocation in bytes. * @param inFileName the name of the source file in which the * allocation took place. * @param inLineNumber the line number in the source file * on which the allocation took place. */ static void addAllocation( void *inPointer, unsigned int inAllocationSize, int inAllocationType, const char *inFileName, int inLineNumber ); /** * Adds a deallocation to this tracker and clears the block * to be deallocated. * Must be called *before* the memory is deallocated * * @param inPointer a pointer to the memory being deallocated. * @param inDeallocationType the type of deallocation, * either SINGLE_ALLOCATION or ARRAY_ALLOCATION. * @return 0 if the deallocation deallocates * an allocated block of memory, or 1 if it * deallocates a block of memory that is not currently allocated, * and 2 if it is the wrong deallocation type for the specified * block. */ static int addDeallocation( void *inPointer, int inDeallocationType ); /** * Prints a list of all memory leaks (allocations that have never * been deallocated). */ static void printLeaks(); // these are public so initializer can get to them static MutexLock *mLock; // dummy place holder for list head static AllocationList *mListHead; // true if we're tracking static char mTracking; static int mTotalAllocationSize; static int mTotalDeallocationSize; static int mNumberOfAllocations; protected: /** * Clears memory so that reading from it will not produce * anything useful. Good for checking for reads to memory that * has been deallocated. * * @param inPointer pointer to the memory to clear. * @Param inSize the number of bytes to clear starting at inPointer. */ static void clearMemory( void *inPointer, unsigned int inSize ); }; /** * Class that initializes MemoryTrack's static members. * * *All* files that use MemoryTrack will instantiate a static * instance of this class (see static instance below). * * This class counts how many static instantiations have happened so * far, making sure to init/destroy MemoryTrack's static members only once. * * Adapted from: * http://www.hlrs.de/organization/par/services/tools/docu/kcc/ * tutorials/static_initialization.html */ class MemoryTrackStaticInitCounter { public: MemoryTrackStaticInitCounter() { if( mCount == 0 ) { // allocate static members MemoryTrack::mLock = new MutexLock(); MemoryTrack::mListHead = (AllocationList *) malloc( sizeof( AllocationList ) ); MemoryTrack::mListHead->mPrevious = NULL; MemoryTrack::mListHead->mNext = NULL; MemoryTrack::mTotalAllocationSize = 0; MemoryTrack::mTotalDeallocationSize = 0; MemoryTrack::mNumberOfAllocations = 0; MemoryTrack::mTracking = true; } mCount++; } ~MemoryTrackStaticInitCounter() { mCount--; if( mCount == 0 ) { // print leaks... we should only get here after // all static members of classes that use MemoryTrack // have been destroyed. MemoryTrack::printLeaks(); MemoryTrack::mTracking = false; // deallocate static members free( MemoryTrack::mListHead ); delete MemoryTrack::mLock; } } private: // only allocate/deallocate when mCount == 0 static int mCount; }; // This will be included in *every* file that includes MemoryTrack.h static MemoryTrackStaticInitCounter memoryTrackInitializer; #endif between-6+dfsg1.orig/minorGems/util/development/memory/testDebugMemory.cpp0000640000175000017500000000267711435543337025657 0ustar pabspabs/* * Modification History * * 2002-October-17 Jason Rohrer * Created. * * 2002-October-18 Jason Rohrer * Added static initialization counting class for MemoryTrack. * * 2002-October-19 Jason Rohrer * Removed call to debugMemoryPrintLeaksAndStopTracking. * Made test cases more interesting. * Added test cases for deleting NULL pointers. */ #include "minorGems/util/development/memory/debugMemory.h" #include class TestClass { public: TestClass() { mX = new int[5]; } ~TestClass() { delete [] mX; } int *mX; }; int main() { int *x = new int[5]; printf( "array contents before initializing elements:\n" "%d, %d, %d, %d, %d\n\n", x[0], x[1], x[2], x[3], x[4] ); x[0] = 1; x[1] = 2; x[2] = 3; x[3] = 4; x[4] = 5; printf( "array contents before deleting:\n" "%d, %d, %d, %d, %d\n\n", x[0], x[1], x[2], x[3], x[4] ); delete [] x; printf( "array contents after deleting:\n" "%d, %d, %d, %d, %d\n\n", x[0], x[1], x[2], x[3], x[4] ); int *y = new int[4]; y[0] = 1; TestClass *t = new TestClass(); delete t; int *z = new int[7]; delete z; //delete t; int *badPointer = NULL; delete badPointer; int *badPointer2 = NULL; delete [] badPointer2; return 0; } between-6+dfsg1.orig/minorGems/util/SettingsManager.h0000640000175000017500000002037411435543337021440 0ustar pabspabs/* * Modification History * * 2002-September-16 Jason Rohrer * Created. * Fixed a memory leak. * * 2002-September-25 Jason Rohrer * Added a setSetting function that takes a string value. * * 2002-September-26 Jason Rohrer * Added functions for integer values. * * 2003-August-24 Jason Rohrer * Fixed to remove 499-character limit for a setting value. * * 2009-February-11 Jason Rohrer * Made getSettingsFile public to support arbitry binary data in settings. * * 2009-February-12 Jason Rohrer * Added support for secure hashing. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ #include "minorGems/common.h" #ifndef SETTINGS_MANAGER_INCLUDED #define SETTINGS_MANAGER_INCLUDED #include "minorGems/util/SimpleVector.h" #include "minorGems/system/MutexLock.h" #include // utility class for dealing with static member dealocation class SettingsManagerStaticMembers; /** * Class that manages program settings. * * @author Jason Rohrer */ class SettingsManager { public: /** * Sets the directory name where settings are stored. * * @param inName the name of the directory (relative to the * program's working directory). * Must be destroyed by caller if non-const. */ static void setDirectoryName( const char *inName ); /** * Gets the directory name where settings are stored. * * @return the name of the directory (relative to the * program's working directory). * Must be destroyed by caller. */ static char *getDirectoryName(); /** * Sets the salt to be used when hashing settings. * * @param inSalt the salt as an ASCII string. * Must be destroyed by caller if non-const. */ static void setHashSalt( const char *inSalt ); /** * Gets the salt to be used when hashing settings. * * @return the hash salt. * Must be destroyed by caller. */ static char *getHashSalt(); /** * Turns hashing on or off. If off, manager will reject * settings in folder that do not have proper hashes. * * @param inOn true to turn hashing on. */ static void setHashingOn( char inOn ); /** * Gets a setting. * * @param inSettingName the name of the setting to get. * Must be destroyed by caller if non-const. * * @return a vector of strings representing the setting value. * The vector and the strings it contains must be destroyed * by the caller. */ static SimpleVector *getSetting( const char *inSettingName ); /** * Gets a string setting. * * @param inSettingName the name of the setting to get. * Must be destroyed by caller if non-const. * * @return the setting value string, or NULL if no setting * value can be read. * Must be destroyed by caller if non-NULL. */ static char *getStringSetting( const char *inSettingName ); /** * Gets a float setting. * * @param inSettingName the name of the setting to get. * Must be destroyed by caller if non-const. * @param outValueFound pointer to where flag should be returned * indicating whether or not the value was found. * Set to true if the value was found, false otherwise. * * @return the setting value. */ static float getFloatSetting( const char *inSettingName, char *outValueFound ); /** * Gets an integer setting. * * @param inSettingName the name of the setting to get. * Must be destroyed by caller if non-const. * @param outValueFound pointer to where flag should be returned * indicating whether or not the value was found. * Set to true if the value was found, false otherwise. * * @return the setting value. */ static int getIntSetting( const char *inSettingName, char *outValueFound ); /** * Sets a setting. * * @param inSettingName the name of the setting to set. * Must be destroyed by caller if non-const. * @param inSettingVector a vector of strings representing the * setting value. * The vector and the strings it contains must be destroyed * by the caller. */ static void setSetting( const char *inSettingName, SimpleVector *inSettingVector ); /** * Sets a setting to a single float value. * * @param inSettingName the name of the setting to set. * Must be destroyed by caller if non-const. * @param inSettingValue the value to set. */ static void setSetting( const char *inSettingName, float inSettingValue ); /** * Sets a setting to a single int value. * * @param inSettingName the name of the setting to set. * Must be destroyed by caller if non-const. * @param inSettingValue the value to set. */ static void setSetting( const char *inSettingName, int inSettingValue ); /** * Sets a setting to a single string value. * * @param inSettingName the name of the setting to set. * Must be destroyed by caller if non-const. * @param inSettingValue the value to set. * Must be destroyed by caller. */ static void setSetting( const char *inSettingName, const char *inSettingValue ); /** * Gets the file for a setting name. * * @param inSettingName the name of the setting. * Must be destroyed by caller if non-const. * @param inReadWriteFlags the flags to pass into the * fopen call. For example, "r" or "w". * * @return the file descriptor, or NULL if the open failed. * Must be fclose()'d by caller if non-NULL. */ static FILE *getSettingsFile( const char *inSettingName, const char *inReadWriteFlags ); protected: static SettingsManagerStaticMembers mStaticMembers; static char mHashingOn; /** * Gets the file name for a setting with the default ini extension. * The .ini extension is added automatically by this call. * * @param inSettingName the name of the setting. * Must be destroyed by caller if non-const. * * @return the name of the settings file. * Must be destroyed by caller. */ static char *getSettingsFileName( const char *inSettingName ); /** * Gets the file name for a setting with a custom extension. * The extension should be passed in without a period in it. * * @param inSettingName the name of the setting. * Must be destroyed by caller if non-const. * @param inExtension the extension to add to the name. * Example: "ini" * Must be destroyed by caller if non-const. * * @return the name of the settings file. * Must be destroyed by caller. */ static char *getSettingsFileName( const char *inSettingName, const char *inExtension ); }; /** * Container for static members to allow for their proper destruction * on program termination. * * @author Jason Rohrer */ class SettingsManagerStaticMembers { public: SettingsManagerStaticMembers(); ~SettingsManagerStaticMembers(); char *mDirectoryName; char *mHashSalt; }; #endif between-6+dfsg1.orig/minorGems/util/CircularBuffer.h0000640000175000017500000000614111435543337021237 0ustar pabspabs/* * Modification History * * 2001-Janary-11 Jason Rohrer * Created. * * 2001-Janary-12 Jason Rohrer * Added canRead and canWrite functions. * * 2001-February-24 Jason Rohrer * Fixed incorrect delete usage. */ #include "minorGems/common.h" #ifndef CIRCULAR_BUFFER_INCLUDED #define CIRCULAR_BUFFER_INCLUDED #include "minorGems/system/Semaphore.h" /** * Thread-safe circular buffer. * * @author Jason Rohrer */ class CircularBuffer { public: /** * Constructs a CircularBuffer. * * @param inSize the number of objects in this buffer. */ CircularBuffer( unsigned long inSize ); ~CircularBuffer(); /** * Writes an object into the next free position in the buffer. * Blocks if no free positions are available. * * @param inObject the object pointer to write. */ void writeObject( void *inObject ); /** * Reads the next available object from the buffer. * Blocks if now objects are available. * * @return the object pointer read. */ void *readNextObject(); /** * Returns true if an object can be read from this buffer * without blocking. */ char canRead(); /** * Returns true if an object can be written to this buffer * without blocking. */ char canWrite(); private: unsigned long mBufferSize; void **mObjects; unsigned long mReadIndex, mWriteIndex; // initialized to 0 Semaphore *mReadSemaphore; // initialized to mBufferSize; Semaphore *mWriteSemaphore; MutexLock *mLock; }; inline CircularBuffer::CircularBuffer( unsigned long inSize ) : mBufferSize( inSize ), mObjects( new void*[inSize] ), mReadIndex( 0 ), mWriteIndex( 0 ), mReadSemaphore( new Semaphore( 0 ) ), mWriteSemaphore( new Semaphore( inSize ) ), mLock( new MutexLock() ) { } inline CircularBuffer::~CircularBuffer() { delete [] mObjects; delete mReadSemaphore; delete mWriteSemaphore; delete mLock; } // note that in this implementation, no mutex is needed, since // reader and writer are never accessing the same data members // simultaneously inline void CircularBuffer::writeObject( void *inObject ) { // wait to for a space to write into mWriteSemaphore->wait(); // write, and increment our write location mObjects[ mWriteIndex ] = inObject; mWriteIndex++; mWriteIndex = mWriteIndex % mBufferSize; // signal the reader that an new object is ready mReadSemaphore->signal(); } inline void *CircularBuffer::readNextObject() { void *returnObject; // wait for an object to read mReadSemaphore->wait(); // read the object, and increment our read location returnObject = mObjects[ mReadIndex ]; mReadIndex++; mReadIndex = mReadIndex % mBufferSize; // signal the writer mWriteSemaphore->signal(); // now return the object that we retrieved from the buffer return returnObject; } inline char CircularBuffer::canRead() { // can read if the read semaphore won't block return ! mReadSemaphore->willBlock(); } inline char CircularBuffer::canWrite() { // can write if the write semaphore won't block return ! mWriteSemaphore->willBlock(); } #endif between-6+dfsg1.orig/minorGems/util/SettingsManager.cpp0000640000175000017500000002127211435543337021771 0ustar pabspabs/* * Modification History * * 2002-September-16 Jason Rohrer * Created. * Fixed a memory leak. * * 2002-September-25 Jason Rohrer * Added a setSetting function that takes a string value. * * 2002-September-26 Jason Rohrer * Added functions for integer values. * * 2003-January-11 Jason Rohrer * Added default values for float and int settings. * * 2003-August-24 Jason Rohrer * Fixed to remove 499-character limit for a setting value. * * 2009-February-12 Jason Rohrer * Added support for secure hashing. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ #include "SettingsManager.h" #include "minorGems/util/stringUtils.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/Path.h" #include "minorGems/crypto/hashes/sha1.h" // will be destroyed automatically at program termination SettingsManagerStaticMembers SettingsManager::mStaticMembers; char SettingsManager::mHashingOn = false; void SettingsManager::setDirectoryName( const char *inName ) { delete [] mStaticMembers.mDirectoryName; mStaticMembers.mDirectoryName = stringDuplicate( inName ); } char *SettingsManager::getDirectoryName() { return stringDuplicate( mStaticMembers.mDirectoryName ); } void SettingsManager::setHashSalt( const char *inSalt ) { delete [] mStaticMembers.mHashSalt; mStaticMembers.mHashSalt = stringDuplicate( inSalt ); } char *SettingsManager::getHashSalt() { return stringDuplicate( mStaticMembers.mHashSalt ); } void SettingsManager::setHashingOn( char inOn ) { mHashingOn = inOn; } SimpleVector *SettingsManager::getSetting( const char *inSettingName ) { char *fileName = getSettingsFileName( inSettingName ); File *settingsFile = new File( NULL, fileName ); delete [] fileName; char *fileContents = settingsFile->readFileContents(); delete settingsFile; if( fileContents == NULL ) { // return empty vector return new SimpleVector(); } if( mHashingOn ) { char *hashFileName = getSettingsFileName( inSettingName, "hash" ); File *hashFile = new File( NULL, hashFileName ); delete [] hashFileName; char *savedHash = hashFile->readFileContents(); delete hashFile; if( savedHash == NULL ) { printf( "Hash missing for setting %s\n", inSettingName ); delete [] fileContents; return new SimpleVector(); } // compute hash char *stringToHash = autoSprintf( "%s%s", fileContents, mStaticMembers.mHashSalt ); char *hash = computeSHA1Digest( stringToHash ); delete [] stringToHash; int difference = strcmp( hash, savedHash ); delete [] hash; delete [] savedHash; if( difference != 0 ) { printf( "Hash mismatch for setting %s\n", inSettingName ); delete [] fileContents; return new SimpleVector(); } } // else tokenize the file contents SimpleVector *returnVector = tokenizeString( fileContents ); delete [] fileContents; return returnVector; } char *SettingsManager::getStringSetting( const char *inSettingName ) { char *value = NULL; SimpleVector *settingsVector = getSetting( inSettingName ); int numStrings = settingsVector->size(); if( numStrings >= 1 ) { char *firstString = *( settingsVector->getElement( 0 ) ); value = stringDuplicate( firstString ); } for( int i=0; igetElement( i ) ); delete [] nextString; } delete settingsVector; return value; } float SettingsManager::getFloatSetting( const char *inSettingName, char *outValueFound ) { char valueFound = false; float value = 0; char *stringValue = getStringSetting( inSettingName ); if( stringValue != NULL ) { int numRead = sscanf( stringValue, "%f", &value ); if( numRead == 1 ) { valueFound = true; } delete [] stringValue; } *outValueFound = valueFound; return value; } int SettingsManager::getIntSetting( const char *inSettingName, char *outValueFound ) { char valueFound = false; int value = 0; char *stringValue = getStringSetting( inSettingName ); if( stringValue != NULL ) { int numRead = sscanf( stringValue, "%d", &value ); if( numRead == 1 ) { valueFound = true; } delete [] stringValue; } *outValueFound = valueFound; return value; } void SettingsManager::setSetting( const char *inSettingName, SimpleVector *inSettingVector ) { char **settingParts = inSettingVector->getElementArray(); char *settingString = join( settingParts, inSettingVector->size(), "\n" ); delete [] settingParts; if( mHashingOn ) { // compute hash char *stringToHash = autoSprintf( "%s%s", settingString, mStaticMembers.mHashSalt ); char *hash = computeSHA1Digest( stringToHash ); delete [] stringToHash; char *hashFileName = getSettingsFileName( inSettingName, "hash" ); FILE *file = fopen( hashFileName, "w" ); delete [] hashFileName; if( file != NULL ) { fprintf( file, "%s", hash ); fclose( file ); } delete [] hash; } FILE *file = getSettingsFile( inSettingName, "w" ); if( file != NULL ) { fprintf( file, "%s", settingString ); fclose( file ); } delete [] settingString; // else do nothing } void SettingsManager::setSetting( const char *inSettingName, float inSettingValue ) { char *valueString = new char[ 15 ]; sprintf( valueString, "%f", inSettingValue ); setSetting( inSettingName, valueString ); delete [] valueString; } void SettingsManager::setSetting( const char *inSettingName, int inSettingValue ) { char *valueString = new char[ 15 ]; sprintf( valueString, "%d", inSettingValue ); setSetting( inSettingName, valueString ); delete [] valueString; } void SettingsManager::setSetting( const char *inSettingName, const char *inSettingValue ) { SimpleVector *settingsVector = new SimpleVector( 1 ); settingsVector->push_back( (char *)inSettingValue ); setSetting( inSettingName, settingsVector ); delete settingsVector; } FILE *SettingsManager::getSettingsFile( const char *inSettingName, const char *inReadWriteFlags ) { char *fullFileName = getSettingsFileName( inSettingName ); FILE *file = fopen( fullFileName, inReadWriteFlags ); delete [] fullFileName; return file; } char *SettingsManager::getSettingsFileName( const char *inSettingName ) { return getSettingsFileName( inSettingName, "ini" ); } char *SettingsManager::getSettingsFileName( const char *inSettingName, const char *inExtension ) { char **pathSteps = new char*[1]; pathSteps[0] = mStaticMembers.mDirectoryName; char *fileName = new char[ strlen( inSettingName ) + strlen( inExtension ) + 2 ]; sprintf( fileName, "%s.%s", inSettingName, inExtension ); File *settingsFile = new File( new Path( pathSteps, 1, false ), fileName ); delete [] fileName; // pathSteps copied internally by Path constructor delete [] pathSteps; char *fullFileName = settingsFile->getFullFileName(); delete settingsFile; return fullFileName; } SettingsManagerStaticMembers::SettingsManagerStaticMembers() : mDirectoryName( stringDuplicate( "settings" ) ), mHashSalt( stringDuplicate( "default_salt" ) ) { } SettingsManagerStaticMembers::~SettingsManagerStaticMembers() { delete [] mDirectoryName; delete [] mHashSalt; } between-6+dfsg1.orig/minorGems/util/random/0000750000175000017500000000000011435543340017437 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/util/random/Noise.h0000640000175000017500000000473211435543337020702 0ustar pabspabs// Jason Rohrer // Noise.h /** * * Noise generation interface * * * Created 11-3-99 * Mods: * Jason Rohrer 12-20-2000 Added a fractal noise function * that fills a double array. * */ #include "minorGems/common.h" #ifndef NOISE_INCLUDED #define NOISE_INCLUDED #include #include #include "RandomSource.h" // fills 2d image with RGBA noise void genRandNoise2d(unsigned long *buff, int buffHigh, int buffWide); // returns a random floating point between 0 and 1 inline float floatRand() { float invRandMax = 1 / ((float)RAND_MAX); return (float)(rand()) * invRandMax; } // fills 2d image with ARGB fractal noise void genFractalNoise2d(unsigned long *buff, int buffHigh, int buffWide); /** * Fills a 2d array with 1/f fractal noise. * * @param inBuffer a pre-allocated buffer to fill. * @param inWidth the width and height of the 2d array * contained in the buffer. * Must be a power of 2. * @param inMaxFrequency the maximum frequency of noise modulation to * include, in [2,inWidth]. Lower values produce more "blurry" or * blocky noise. * @param inFPower power to raise F to whene generating noise. * Amplitude of modulation = 1 / (F^inFPower). * @param inInterpolate set to true to perform interpolation of * each frequency modulation. Setting to false produces a "blockier" * noise, while setting to true makes the noise more cloud-like. * @param inRandSource the source to use for random numbers. */ void genFractalNoise2d( double *inBuffer, int inWidth, int inMaxFrequency, double inFPower, char inInterpolate, RandomSource *inRandSource ); /** * Fills a 1d array with 1/f fractal noise. * * @param inBuffer a pre-allocated buffer to fill. * @param inWidth the width of the 2d array * contained in the buffer. * Must be a power of 2. * @param inMaxFrequency the maximum frequency of noise modulation to * include, in [2,inWidth]. Lower values produce more "blurry" or * blocky noise. * @param inFPower power to raise F to whene generating noise. * Amplitude of modulation = 1 / (F^inFPower). * @param inInterpolate set to true to perform interpolation of * each frequency modulation. Setting to false produces a "blockier" * noise, while setting to true makes the noise more cloud-like. * @param inRandSource the source to use for random numbers. */ void genFractalNoise( double *inBuffer, int inWidth, int inMaxFrequency, double inFPower, char inInterpolate, RandomSource *inRandSource ); #endif between-6+dfsg1.orig/minorGems/util/random/testRandom.cpp0000640000175000017500000001141311435543340022264 0ustar pabspabs#include "RandomSource.h" #include // perform tests on a random source // tests found here: // NIST FIPS 140-1 U.S. Federal Standard // http://csrc.nist.gov/publications/fips/fips140-1/fips1401.pdf void testRandom( RandomSource *inSource ) { int bitsPerStep = 1; // 20000 bits // must be a multiple of bitsPerStep int numBits = 20000; int numSteps = numBits / bitsPerStep; unsigned int *drawnNumbers = new unsigned int[ numSteps ]; unsigned int *drawnBits = new unsigned int[ numBits ]; unsigned int bitSum = 0; // 1 or 0 when we're in a run unsigned int currentRunType = 2; unsigned int currentRunLength = 0; unsigned int longestRunLength = 0; #define maxRunLengthToTrack 100 unsigned int runLengthCounts[2][ maxRunLengthToTrack ]; int r; for( r=0; rgetRandomBoundedInt( 0, 1 ); //drawnNumbers[i] = inSource->getRandomBoolean(); for( int b=0; b> b & 0x01 ); bitSum += bit; drawnBits[bitIndex] = bit; bitIndex++; if( bit == currentRunType ) { currentRunLength++; if( currentRunLength > longestRunLength ) { longestRunLength = currentRunLength; } } else { // end of run if( currentRunLength > 0 && currentRunLength < maxRunLengthToTrack ) { // count it runLengthCounts[currentRunType][ currentRunLength ] ++; } currentRunType = bit; currentRunLength = 1; } } } float mean = (float)bitSum / numBits; printf( "Mean = %f\n", mean ); float varSum = 0; for( i=0; i 2326 && Z[t] < 2674 ) { } else { failed = true; //printf( "autocorrelation test failed for Z[%d] = %d\n", t, Z[t] ); } } if( !failed ) { printf( "Autocorrelation test passed.\n" ); } delete [] drawnNumbers; delete [] drawnBits; } #include "CustomRandomSource.h" #include "StdRandomSource.h" int main() { CustomRandomSource randSource( 11234258 ); //StdRandomSource randSource( 11 ); testRandom( &randSource ); return 0; } between-6+dfsg1.orig/minorGems/util/random/CustomRandomSource.h0000640000175000017500000001146611435543337023423 0ustar pabspabs/* * Modification History * * 2009-January-14 Jason Rohrer * Created. * * 2009-February-5 Jason Rohrer * Added support for restoring from saved state. * */ #ifndef CUSTOM_RANDOM_SOURCE_INCLUDED #define CUSTOM_RANDOM_SOURCE_INCLUDED #include #include #include "RandomSource.h" /** * Implementation of RandomSource that does not depend on platform or library. * * Maintains its own internal state. */ class CustomRandomSource : public RandomSource { public: // seeds itself with current time CustomRandomSource(); // specify the seed CustomRandomSource( unsigned int inSeed ); // save for rewind later void saveState(); void rewindState(); // can be used to save state to disk unsigned int getSavedState(); void restoreFromSavedState( unsigned int inSavedState ); void reseed( unsigned int inSeed ); // implements these functions float getRandomFloat(); // in interval [0,1.0] double getRandomDouble(); // in interval [0,1.0] unsigned int getRandomInt(); // in interval [0,MAX] unsigned int getIntMax(); // returns MAX int getRandomBoundedInt( int inRangeStart, int inRangeEnd ); double getRandomBoundedDouble( double inRangeStart, double inRangeEnd ); char getRandomBoolean(); private: double mInvMAXPlusOne; // 1 / ( MAX + 1 ) unsigned int mState; unsigned int mSavedState; // returns next number and updates state unsigned int genRand32(); }; inline CustomRandomSource::CustomRandomSource() { MAX = 4294967295U; mState = (unsigned)( time(NULL) ); invMAX = (float)1.0 / ((float)MAX); invDMAX = 1.0 / ((double)MAX); mInvMAXPlusOne = 1.0 / ( ( (float)MAX ) + 1.0 ); saveState(); } inline CustomRandomSource::CustomRandomSource( unsigned int inSeed ) { MAX = 4294967295U; mState = inSeed; invMAX = (float)1.0 / ((float)MAX); invDMAX = 1.0 / ((double)MAX); mInvMAXPlusOne = 1.0 / ( ( (double)MAX ) + 1.0 ); saveState(); } inline void CustomRandomSource::saveState() { mSavedState = mState; } inline void CustomRandomSource::rewindState() { mState = mSavedState; } inline unsigned int CustomRandomSource::getSavedState() { return mSavedState; } inline void CustomRandomSource::restoreFromSavedState( unsigned int inSavedState) { mState = inSavedState; } inline void CustomRandomSource::reseed( unsigned int inSeed ) { mState = inSeed; } // from Cultivation/Passage's landscape.cpp // faster as a set of macros #define CustNum1( inSeed ) \ ( ( inSeed * 0xFEA09B9DU ) + 1 ) #define CustNum2( inSeed ) \ ( ( ( inSeed ^ CustNum1( inSeed ) ) * 0x9C129511U ) + 1 ) #define CustNum3( inSeed ) \ ( ( inSeed * 0x2512CFB8U ) + 1 ) #define CustNum4( inSeed ) \ ( ( ( inSeed ^ CustNum3( inSeed ) ) * 0xB89C8895U ) + 1 ) #define CustNum5( inSeed ) \ ( ( inSeed * 0x6BF962C1U ) + 1 ) #define CustNum6( inSeed ) \ ( ( ( inSeed ^ CustNum5( inSeed ) ) * 0x4BF962C1U ) + 1 ) inline unsigned int CustomRandomSource::genRand32() { mState = CustNum2( mState ) ^ (CustNum4( mState ) >> 11) ^ (CustNum6( mState ) >> 22); return mState; } inline float CustomRandomSource::getRandomFloat() { return (float)(genRand32()) * invMAX; } inline double CustomRandomSource::getRandomDouble() { return (double)(genRand32()) * invDMAX; } inline unsigned int CustomRandomSource::getRandomInt() { return genRand32(); } inline unsigned int CustomRandomSource::getIntMax() { return MAX; } inline int CustomRandomSource::getRandomBoundedInt( int inRangeStart, int inRangeEnd ) { // float in range [0,1) double randFloat = (double)( genRand32() ) * mInvMAXPlusOne; int onePastRange = inRangeEnd + 1; int magnitude = (int)( randFloat * ( onePastRange - inRangeStart ) ); return magnitude + inRangeStart; } inline double CustomRandomSource::getRandomBoundedDouble( double inRangeStart, double inRangeEnd ) { // double in range [0,1] double randDouble = getRandomDouble(); double magnitude = randDouble * ( inRangeEnd - inRangeStart ); return magnitude + inRangeStart; } inline char CustomRandomSource::getRandomBoolean() { // float in range [0,1] double randFloat = getRandomFloat(); if( randFloat < 0.5 ) { return true; } else { return false; } } #endif between-6+dfsg1.orig/minorGems/util/random/RandomSource.h0000640000175000017500000000401411435543337022217 0ustar pabspabs// Jason Rohrer // RandomSource.h /** * * abstract interface for random number generation * * Can be implemented by: * --stdlib rand() function calls * --seed file full of random numbers * * Created 12-7-99 * Mods: * Jason Rohrer 9-28-2000 Added a getRandomBoundedInt() * interface to faciliate retrieving * an integer in a given range [a,b] * where each integer in the range * has the same probability of being * returned. * Jason Rohrer 12-16-2000 Added a getRandomDouble() interface. * Jason Rohrer 11-21-2005 Added a virtual destructor. * Jason Rohrer 07-09-2006 Added a getRandomBoundedDouble interface. * Jason Rohrer 07-27-2006 Added a getRandomBoolean interface. */ #include "minorGems/common.h" #ifndef RANDOM_SOURCE_INCLUDED #define RANDOM_SOURCE_INCLUDED class RandomSource { public: // pure virtual functions implemented by inheriting classes virtual float getRandomFloat() = 0; // in interval [0,1.0] virtual double getRandomDouble() = 0; // in interval [0,1.0] virtual unsigned int getRandomInt() = 0; // in interval [0,MAX] virtual unsigned int getIntMax() = 0; // returns MAX /** * Returns a random integer in [rangeStart,rangeEnd] * where each integer in the range has an equal * probability of occuring. */ virtual int getRandomBoundedInt( int inRangeStart, int inRangeEnd ) = 0; /** * Returns a random double in [rangeStart,rangeEnd]. */ virtual double getRandomBoundedDouble( double inRangeStart, double inRangeEnd ) = 0; /** * Gets a random true/false value. */ virtual char getRandomBoolean() = 0; virtual ~RandomSource(); protected: unsigned int MAX; // maximum integer random number float invMAX; // floating point inverse of MAX double invDMAX; // double invers of MAX }; inline RandomSource::~RandomSource() { // does nothing // exists to ensure that subclass destructors are called } #endif between-6+dfsg1.orig/minorGems/util/random/StdRandomSource.h0000640000175000017500000000641311435543337022677 0ustar pabspabs// Jason Rohrer // StdRandomSource.h /** * * Implementation of random number generation that uses stdlib calls * * * Created 12-7-99 * Mods: * Jason Rohrer 9-28-2000 Added a getRandomBoundedInt() * implementation * Jason Rohrer 12-7-2000 Overloaded constructor to support * specifying a seed. * Jason Rohrer 12-16-2000 Added a getRandomDouble() function. * Jason Rohrer 12-17-2000 Fixed bug in initialization of invDMAX * in default constructor. * Jason Rohrer 9-13-2001 Fixed a bug in getRandomBoundedInt() * as floats were being used, and they * don't provide enough resolution. * Jason Rohrer 10-11-2002 Fixed some type casting warnings. * Jason Rohrer 07-09-2006 Added getRandomBoundedDouble. * Jason Rohrer 07-27-2006 Added getRandomBoolean. */ #include "minorGems/common.h" #ifndef STD_RANDOM_SOURCE_INCLUDED #define STD_RANDOM_SOURCE_INCLUDED #include #include #include "RandomSource.h" class StdRandomSource : public RandomSource { public: StdRandomSource(); // needed to seed stdlib generator // specify the seed for the stdlib generator StdRandomSource( unsigned int inSeed ); // implements these functions float getRandomFloat(); // in interval [0,1.0] double getRandomDouble(); // in interval [0,1.0] unsigned int getRandomInt(); // in interval [0,MAX] unsigned int getIntMax(); // returns MAX int getRandomBoundedInt( int inRangeStart, int inRangeEnd ); double getRandomBoundedDouble( double inRangeStart, double inRangeEnd ); char getRandomBoolean(); private: double mInvMAXPlusOne; // 1 / ( MAX + 1 ) }; inline StdRandomSource::StdRandomSource() { MAX = RAND_MAX; srand( (unsigned)time(NULL) ); invMAX = (float)1.0 / ((float)MAX); invDMAX = 1.0 / ((double)MAX); mInvMAXPlusOne = 1.0 / ( ( (float)MAX ) + 1.0 ); } inline StdRandomSource::StdRandomSource( unsigned int inSeed ) { MAX = RAND_MAX; srand( inSeed ); invMAX = (float)1.0 / ((float)MAX); invDMAX = 1.0 / ((double)MAX); mInvMAXPlusOne = 1.0 / ( ( (double)MAX ) + 1.0 ); } inline float StdRandomSource::getRandomFloat() { return (float)(rand()) * invMAX; } inline double StdRandomSource::getRandomDouble() { return (double)(rand()) * invDMAX; } inline unsigned int StdRandomSource::getRandomInt() { return rand(); } inline unsigned int StdRandomSource::getIntMax() { return MAX; } inline int StdRandomSource::getRandomBoundedInt( int inRangeStart, int inRangeEnd ) { // float in range [0,1) double randFloat = (double)( rand() ) * mInvMAXPlusOne; int onePastRange = inRangeEnd + 1; int magnitude = (int)( randFloat * ( onePastRange - inRangeStart ) ); return magnitude + inRangeStart; } inline double StdRandomSource::getRandomBoundedDouble( double inRangeStart, double inRangeEnd ) { // double in range [0,1] double randDouble = getRandomDouble(); double magnitude = randDouble * ( inRangeEnd - inRangeStart ); return magnitude + inRangeStart; } inline char StdRandomSource::getRandomBoolean() { // float in range [0,1] double randFloat = getRandomFloat(); if( randFloat < 0.5 ) { return true; } else { return false; } } #endif between-6+dfsg1.orig/minorGems/util/random/Noise.cpp0000640000175000017500000001625411435543337021237 0ustar pabspabs// Jason Rohrer // Noise.cpp /** * * Noise generation implementation * * * Created 11-3-99 * Mods: * Jason Rohrer 12-20-2000 Changed genFractalNoise2d function to make * it less blocky. * */ #include "Noise.h" // fills 2d image with ARGB noise void genRandNoise2d(unsigned long *buff, int buffHigh, int buffWide) { int *yOffset = new int[buffHigh]; // precalc y offsets for( int y=0; y> 24 & 0xFF) + alpha; int buffRed = (buffARGB >> 16 & 0xFF) + red; int buffGreen = (buffARGB >> 8 & 0xFF) + green; int buffBlue = (buffARGB & 0xFF) + blue; if( buffAlpha < 0) buffAlpha = 0; if( buffRed < 0) buffRed = 0; if( buffGreen < 0) buffGreen = 0; if( buffBlue < 0) buffBlue = 0; if( buffAlpha > 255) buffAlpha = 255; if( buffRed > 255) buffRed = 255; if( buffGreen > 255) buffGreen = 255; if( buffBlue > 255) buffBlue = 255; buff[ yOffset[buffY] + buffX] = buffBlue | buffGreen << 8 | buffRed << 16 | buffAlpha << 24; buffX++; blockX++; if( buffX >= buffWide ) blockX = blockWide; // if this block hangs outside buffer } buffY++; blockY++; if( buffY >= buffHigh ) blockY = blockHigh; // if this block hangs outside buffer } buffX = startX + blockWide; } buffY = startY + blockHigh; } } delete [] yOffset; } void genFractalNoise2d( double *inBuffer, int inWidth, int inMaxFrequency, double inFPower, char inInterpolate, RandomSource *inRandSource ) { RandomSource *r = inRandSource; int w = inWidth; int i, x, y, f; int numPoints = w * w; // first, fill surface with a uniform 0.5 value for( i=0; igetRandomDouble() - 1 ) * weight; } // now walk though 2d array and perform // bilinear interpolation between blocks for( y=0; y 1.0 ) { inBuffer[y * w + x] = 1.0; } else if( inBuffer[y * w + x] < 0.0 ) { inBuffer[y * w + x] = 0.0; } } } delete [] blockValues; } } void genFractalNoise( double *inBuffer, int inWidth, int inMaxFrequency, double inFPower, char inInterpolate, RandomSource *inRandSource ) { RandomSource *r = inRandSource; int w = inWidth; int i, x, f; // first, fill array with uniform 0.5 values for( i=0; igetRandomDouble() - 1 ) * weight; } // now walk though array and perform linear interpolation between blocks for( x=0; x 1.0 ) { inBuffer[x] = 1.0; } else if( inBuffer[x] < 0.0 ) { inBuffer[x] = 0.0; } } delete [] blockValues; } } between-6+dfsg1.orig/minorGems/util/stringUtils.h0000640000175000017500000002153311435543340020664 0ustar pabspabs/* * Modification History * * 2002-April-6 Jason Rohrer * Created. * * 2002-April-8 Jason Rohrer * Fixed multiple inclusion bug * * 2002-May-7 Jason Rohrer * Added functions for case-insensitive substring finding and case * conversion. * * 2002-May-9 Jason Rohrer * Fixed a bug when string not found. * * 2002-May-26 Jason Rohrer * Added a function for string comparison ignoring cases. * * 2003-March-28 Jason Rohrer * Added split function. * * 2003-May-1 Jason Rohrer * Added replacement functions. * * 2003-May-4 Jason Rohrer * Added list replacement function. * * 2003-May-10 Jason Rohrer * Moved implementations into a .cpp file. This will break several * projects. * Added a tokenization function. * * 2003-June-14 Jason Rohrer * Added a join function. * * 2003-June-22 Jason Rohrer * Added an autoSprintf function. * * 2003-August-12 Jason Rohrer * Added a concatonate function. * * 2003-September-7 Jason Rohrer * Improved split comment. * * 2006-June-2 Jason Rohrer * Added a stringStartsWith function. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ #include "minorGems/common.h" #include "minorGems/util/SimpleVector.h" #ifndef STRING_UTILS_INCLUDED #define STRING_UTILS_INCLUDED // ANSI does not support strdup, strcasestr, or strcasecmp #include #include #include /** * Duplicates a string into a newly allocated string. * * @param inString the \0-terminated string to duplicate. * Must be destroyed by caller if non-const. * * @return a \0-terminated duplicate of inString. * Must be destroyed by caller. */ inline char *stringDuplicate( const char *inString ) { char *returnBuffer = new char[ strlen( inString ) + 1 ]; strcpy( returnBuffer, inString ); return returnBuffer; } /** * Converts a string to lower case. * * @param inString the \0-terminated string to convert. * Must be destroyed by caller if non-const. * * @return a newly allocated \0-terminated string * that is a lowercase version of inString. * Must be destroyed by caller. */ char *stringToLowerCase( const char *inString ); /** * Searches for the first occurrence of one string in another. * * @param inHaystack the \0-terminated string to search in. * Must be destroyed by caller if non-const. * @param inNeedle the \0-terminated string to search for. * Must be destroyed by caller if non-const. * * @return a string pointer into inHaystack where the * first occurrence of inNeedle starts, or NULL if inNeedle is not found. */ char *stringLocateIgnoreCase( const char *inHaystack, const char *inNeedle ); /** * Compares two strings, ignoring case. * * @param inStringA the first \0-terminated string. * Must be destroyed by caller if non-const. * @param inStringB the second \0-terminated string. * Must be destroyed by caller if non-const. * * @return an integer less than, equal to, or greater than zero if * inStringA is found, respectively, to be less than, to match, or be * greater than inStringB. */ int stringCompareIgnoreCase( const char *inStringA, const char *inStringB ); /** * Checks if a string starts with a given prefix string. * * @param inString a \0-terminated string. * Must be destroyed by caller if non-const. * @param inPrefix the prefix to look for as a \0-terminated string. * Must be destroyed by caller if non-const. * * @return true if inString begins with inPrefix, or false otherwise. */ char stringStartsWith( const char *inString, const char *inPrefix ); /** * Splits a string into parts around a separator string. * * Note that splitting strings that start and/or end with the separator * results in "empty" strings being returned at the start and/or end * of the parts array. * * For example, splitting "a#short#test" around the "#" separator will * result in the array { "a", "short", "test" }, but splitting * "#another#short#test#" will result in the array * { "", "another", "short", "test", "" }. * * This differs somewhat from the perl version of split, but it gives the * caller more information about the string being split. * * @param inString the string to split. * Must be destroyed by caller if non-const. * @param inSeparator the separator string. * Must be destroyed by caller if non-const. * @param outNumParts pointer to where the the number of parts (the length of * the returned array) should be returned. * * @return an array of split parts. * Must be destroyed by caller. */ char **split( const char *inString, const char *inSeparator, int *outNumParts ); /** * Joins a collection of strings using a separator string. * * @param inStrings the strings to join. * Array and strings must be destroyed by caller. * @param inNumParts the number of strings to join. * @param inSeparator the separator string. * Must be destroyed by caller if non-const. * * @return the joined string. * Must be destroyed by caller. */ char *join( char **inStrings, int inNumParts, const char *inGlue ); /** * Concatonates two strings. * * @param inStringA the first string in the concatonation. * Must be destroyed by caller if non-const. * @param inStringB the second string in the concatonation. * Must be destroyed by caller if non-const. * * @return the concatonation. * Must be destroyed by caller. */ char *concatonate( const char *inStringA, const char *inStringB ); /** * Replaces the first occurrence of a target string with * a substitute string. * * All parameters and return value must be destroyed by caller. * * @param inHaystack the string to search for inTarget in. * @param inTarget the string to search for. * @param inSubstitute the string to replace the first occurrence * of the target with. * @param outFound a pre-allocated character which will be filled * with true if the target is found, and filled with false * otherwise. * * @return a newly allocated string with the substitution performed. */ char *replaceOnce( const char *inHaystack, const char *inTarget, const char *inSubstitute, char *outFound ); /** * Replaces the all occurrences of a target string with * a substitute string. * * Note that this function is not self-insertion-safe: * If inSubstitute contains inTarget, this function will * enter an infinite loop. * * All parameters and return value must be destroyed by caller. * * @param inHaystack the string to search for inTarget in. * @param inTarget the string to search for. * @param inSubstitute the string to replace the all occurrences * of the target with. * @param outFound a pre-allocated character which will be filled * with true if the target is found at least once, * and filled with false otherwise. * * @return a newly allocated string with the substitutions performed. */ char *replaceAll( const char *inHaystack, const char *inTarget, const char *inSubstitute, char *outFound ); /** * Replaces the all occurrences of each target string on a list with * a corresponding substitute string. * * Note that this function is not self-insertion-safe: * If inSubstituteVector contains elements from inTargetVector, * this function will enter an infinite loop. * * All parameters and return value must be destroyed by caller. * * @param inHaystack the string to search for targets in. * @param inTargetVector the list of strings to search for. * Vector and contained strings must be destroyed by caller. * @param inSubstituteVector the corresponding list of strings to * replace the all occurrences of the targets with. * Vector and contained strings must be destroyed by caller. * * @return a newly allocated string with the substitutions performed. */ char *replaceTargetListWithSubstituteList( const char *inHaystack, SimpleVector *inTargetVector, SimpleVector *inSubstituteVector ); /** * Split a string into tokens using whitespace as separators. * * @param inString the string to tokenize. * Must be destroyed by caller. * * @return a vector of extracted strings. * Vector and strings must be destroyed by caller. */ SimpleVector *tokenizeString( const char *inString ); /** * Prints formatted data elements into a newly allocated string buffer. * * Similar to sprintf, except that buffer sizing is automatic (and therefore * safer than manual sizing). * * @param inFormatString the format string to print from. * @param variable argument list data values to fill in the format string * with (uses same conventions as printf). * * @return a newly allocated buffer containing the \0-terminated printed * string. * Must be destroyed by caller. */ char *autoSprintf( const char* inFormatString, ... ); #endif between-6+dfsg1.orig/minorGems/util/vectorTest.cpp0000640000175000017500000000425711435543340021036 0ustar pabspabs #include "SimpleVector.h" #include class A { public: A() { mV.push_back( 50 ); mV.push_back( 60 ); } ~A() { printf( "A's destructor invoked\n" ); } SimpleVector mV; void print() { printf( "A{ " ); for( int i=0; i v; A a; v.push_back( a ); v.push_back( a ); // push more back to force vector expansion for( int i=0; i<10; i++ ) { v.push_back( a ); } /* printf( "making array\n" ); A *array = new A[100]; printf( "deleting array\n" ); delete [] array; printf( "About to exit\n" ); */ printf( "making w\n" ); SimpleVector w; w.push_back( a ); w.push_back( a ); // push more back to force vector expansion for( int i=0; i<10; i++ ) { w.push_back( a ); } printf( "deleting from w\n" ); // delete a few to test for leak w.deleteElement( 0 ); w.deleteElement( 0 ); { // copy constructor SimpleVector clone = v; printf( "clone = " ); for( int i=0; iprint(); } printf( "\n" ); // assignment operator clone = w; printf( "clone = " ); for( int i=0; iprint(); } printf( "\n" ); // clone deleted here } // v still okay? printf( "v = " ); for( int i=0; iprint(); } printf( "\n" ); // w still okay? printf( "w = " ); for( int i=0; iprint(); } printf( "\n" ); } between-6+dfsg1.orig/minorGems/util/log/0000750000175000017500000000000011435543337016746 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/util/log/PrintLog.h0000640000175000017500000000422611435543337020662 0ustar pabspabs/* * Modification History * * 2002-February-25 Jason Rohrer * Created. * * 2002-April-8 Jason Rohrer * Changed to be thread-safe. * * 2010-April-5 Jason Rohrer * Printf-like functionality. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ #include "minorGems/common.h" #ifndef PRINT_LOG_INCLUDED #define PRINT_LOG_INCLUDED #include "Log.h" #include "minorGems/system/MutexLock.h" /** * A console-based implementation of the Log interface. * * @author Jason Rohrer */ class PrintLog : public Log { public: /** * Constructs a print log. */ PrintLog(); virtual ~PrintLog(); // implement the Log interface virtual void setLoggingLevel( int inLevel ); virtual int getLoggingLevel(); virtual void logString( const char *inString, int inLevel ); virtual void logString( const char *inLoggerName, const char *inString, int inLevel ); virtual void logPrintf( int inLevel, const char* inFormatString, ... ); virtual void logNPrintf( const char *inLoggerName, int inLevel, const char* inFormatString, ... ); protected: int mLoggingLevel; static const char *mDefaultLoggerName; MutexLock *mLock; /** * Generates a string representation of a log message. * * @param inLoggerName the name of the logger * as a \0-terminated string. * Must be destroyed by caller. * @param inString the string to log as a \0-terminated string. * Must be destroyed by caller. * @param inLevel the level to log inString at. * * @return the log message as a \0-terminated string. * Must be destroyed by caller. */ char *generateLogMessage( const char *inLoggerName, const char *inString, int inLevel ); }; #endif between-6+dfsg1.orig/minorGems/util/log/AppLog.h0000640000175000017500000000715111435543337020306 0ustar pabspabs/* * Modification History * * 2002-February-25 Jason Rohrer * Created. * * 2002-March-30 Jason Rohrer * Wrapped our dynamically allocated static member in a statically * allocated class to avoid memory leaks at program termination. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ #include "minorGems/common.h" #ifndef APP_LOG_INCLUDED #define APP_LOG_INCLUDED #include "Log.h" #include "PrintLog.h" // internally used class class LogPointerWrapper; /** * A singleton wrapper for implementations of the Log interface. * * This class should be the interface for log-access for applications. * * @author Jason Rohrer */ class AppLog { public: /** * These log errors at various levels. * * All char* parameters must be \0-terminated and destroyed by caller. */ static void criticalError( const char *inString ); static void criticalError( const char *inLoggerName, const char *inString ); static void error( const char *inString ); static void error( const char *inLoggerName, const char *inString ); static void warning( const char *inString ); static void warning( const char *inLoggerName, const char *inString ); static void info( const char *inString ); static void info( const char *inLoggerName, const char *inString ); static void detail( const char *inString ); static void detail( const char *inLoggerName, const char *inString ); static void trace( const char *inString ); static void trace( const char *inLoggerName, const char *inString ); /** * Sets the log to use. * Note that this call destroys the current log. * * @param inLog the log to use. * Will be destroyed by this class. */ static void setLog( Log *inLog ); /** * Gets the log being used. * * @return the log being used. * Will be destroyed by this class. */ static Log *getLog(); /** * Sets the logging level of the current log. * * Messages with levels above the current level will not be logged. * * @param inLevel one of the defined logging levels. */ static void setLoggingLevel( int inLevel ); /** * Gets the logging level of the current log. * * Messages with levels above the current level will not be logged. * * @return one of the defined logging levels. */ static int getLoggingLevel(); protected: // note that all static objects // are destroyed at program termination //static Log *mLog; static LogPointerWrapper mLogPointerWrapper; }; /** * Wrapper for static member pointer to ensure * deletion of static member object at program termination. */ class LogPointerWrapper { public: /** * Constructor allows specification of the object * to wrap and destroy at program termination. * * @param inLog the log object to wrap. * Will be destroyed at program termination if non-NULL. */ LogPointerWrapper( Log *inLog ); /** * Destructor will get called at program termination * if the object is statically allocated. */ ~LogPointerWrapper(); Log *mLog; }; #endif between-6+dfsg1.orig/minorGems/util/log/FileLog.h0000640000175000017500000000354211435543337020445 0ustar pabspabs/* * Modification History * * 2002-February-25 Jason Rohrer * Created. * * 2002-November-5 Jason Rohrer * Added support for backing up logs and deleting old log data. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ #include "minorGems/common.h" #ifndef FILE_LOG_INCLUDED #define FILE_LOG_INCLUDED #include "PrintLog.h" #include /** * A file-based implementation of the Log interface. * * @author Jason Rohrer */ class FileLog : public PrintLog { public: /** * Constructs a file log. * * @param inFileName the name of the file to write log messages to. * Must be destroyed by caller. * @param inSecondsBetweenBackups the number of seconds to wait * before making a backup of the current log file (deleting any * old backups), clearing the current log file, and starting * a fresh log in the current log file. Defaults to 3600 * seconds (one hour). Backup logs are saved to inFileName.bakup */ FileLog( const char *inFileName, unsigned long inSecondsBetweenBackups = 3600 ); virtual ~FileLog(); /** * Makes a backup of the current log file, deletes old backups, * and clears the current log file. */ void makeBackup(); // overrides PrintLog::logString virtual void logString( const char *inLoggerName, const char *inString, int inLevel ); protected: FILE *mLogFile; char *mLogFileName; unsigned long mSecondsBetweenBackups; unsigned long mTimeOfLastBackup; static const char *mDefaultLogFileName; }; #endif between-6+dfsg1.orig/minorGems/util/log/Makefile0000640000175000017500000000235711435543337020416 0ustar pabspabs# # Modification History # # 2002-February-25 Jason Rohrer # Created. # Changed to be more succinct. # GXX=g++ ROOT_PATH = ../../.. DEBUG_ON_FLAG = -g DEBUG_OFF_FLAG = DEBUG_FLAG = ${DEBUG_OFF_FLAG} TIME_PLATFORM_PATH = unix TIME_PLATFORM = Unix TIME_O = ${ROOT_PATH}/minorGems/system/${TIME_PLATFORM_PATH}/Time${TIME_PLATFORM}.o TIME_H = ${ROOT_PATH}/minorGems/system/Time.h TIME_CPP = ${ROOT_PATH}/minorGems/system/${TIME_PLATFORM_PATH}/Time${TIME_PLATFORM}.cpp testLog: AppLog.o FileLog.o PrintLog.o Log.o testLog.o ${TIME_O} ${GXX} ${DEBUG_FLAG} -o testLog AppLog.o FileLog.o PrintLog.o Log.o testLog.o ${TIME_O} clean: rm -f *.o ${TIME_O} testLog.o: testLog.cpp AppLog.h FileLog.h Log.h ${GXX} ${DEBUG_FLAG} -o testLog.o -c testLog.cpp AppLog.o: AppLog.h AppLog.cpp Log.h PrintLog.h ${GXX} ${DEBUG_FLAG} -o AppLog.o -c AppLog.cpp PrintLog.o: PrintLog.h PrintLog.cpp Log.h PrintLog.h ${TIME_H} ${GXX} ${DEBUG_FLAG} -I${ROOT_PATH} -o PrintLog.o -c PrintLog.cpp FileLog.o: PrintLog.h FileLog.cpp FileLog.h Log.h ${GXX} ${DEBUG_FLAG} -o FileLog.o -c FileLog.cpp Log.o: Log.h Log.cpp ${GXX} ${DEBUG_FLAG} -o Log.o -c Log.cpp ${TIME_O}: ${TIME_H} ${TIME_CPP} ${GXX} ${DEBUG_FLAG} -I${ROOT_PATH} -o ${TIME_O} -c ${TIME_CPP} between-6+dfsg1.orig/minorGems/util/log/FileLog.cpp0000640000175000017500000000613111435543337020775 0ustar pabspabs/* * Modification History * * 2002-February-25 Jason Rohrer * Created. * * 2002-March-13 Jason Rohrer * Added a flush after every write. * * 2002-April-8 Jason Rohrer * Changed to be thread-safe. * * 2002-November-5 Jason Rohrer * Added support for backing up logs and deleting old log data. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ #include "FileLog.h" #include "PrintLog.h" #include "minorGems/util/stringUtils.h" #include "minorGems/io/file/File.h" #include #include const char *FileLog::mDefaultLogFileName = "default.log"; FileLog::FileLog( const char *inFileName, unsigned long inSecondsBetweenBackups ) : mLogFile( NULL ), mLogFileName( stringDuplicate( inFileName ) ), mSecondsBetweenBackups( inSecondsBetweenBackups ), mTimeOfLastBackup( time( NULL ) ) { mLogFile = fopen( mLogFileName, "a" ); if( mLogFile == NULL ) { printf( "Log file %s failed to open.\n", mLogFileName ); printf( "Writing log to default file: %s\n", mDefaultLogFileName ); // switch to default log file name delete [] mLogFileName; mLogFileName = stringDuplicate( mDefaultLogFileName ); mLogFile = fopen( mLogFileName, "a" ); if( mLogFile == NULL ) { printf( "Default log file %s failed to open.\n", mLogFileName ); } } } FileLog::~FileLog() { if( mLogFile != NULL ) { fclose( mLogFile ); } delete [] mLogFileName; } void FileLog::logString( const char *inLoggerName, const char *inString, int inLevel ) { if( mLogFile != NULL ) { if( inLevel <= mLoggingLevel ) { char *message = PrintLog::generateLogMessage( inLoggerName, inString, inLevel ); mLock->lock(); fprintf( mLogFile, "%s\n", message ); fflush( mLogFile ); if( time( NULL ) - mTimeOfLastBackup > mSecondsBetweenBackups ) { makeBackup(); } mLock->unlock(); delete [] message; } } } void FileLog::makeBackup() { fclose( mLogFile ); File *currentLogFile = new File( NULL, mLogFileName ); char *backupFileName = new char[ strlen( mLogFileName ) + 10 ]; sprintf( backupFileName, "%s.backup", mLogFileName ); File *backupLogFile = new File( NULL, backupFileName ); delete [] backupFileName; // copy into backup log file, which will overwrite it currentLogFile->copy( backupLogFile ); delete currentLogFile; delete backupLogFile; // clear main log file and start writing to it again mLogFile = fopen( mLogFileName, "w" ); if( mLogFile == NULL ) { printf( "Log file %s failed to open.\n", mLogFileName ); } mTimeOfLastBackup = time( NULL ); } between-6+dfsg1.orig/minorGems/util/log/AppLog.cpp0000640000175000017500000000603211435543337020636 0ustar pabspabs/* * Modification History * * 2002-February-25 Jason Rohrer * Created. * * 2002-March-30 Jason Rohrer * Wrapped our dynamically allocated static member in a statically * allocated class to avoid memory leaks at program termination. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ #include "AppLog.h" #include "Log.h" #include // wrap our static member in a statically allocated class LogPointerWrapper AppLog::mLogPointerWrapper( new PrintLog ); LogPointerWrapper::LogPointerWrapper( Log *inLog ) : mLog( inLog ) { } LogPointerWrapper::~LogPointerWrapper() { if( mLog != NULL ) { delete mLog; } } void AppLog::criticalError( const char *inString ) { mLogPointerWrapper.mLog->logString( inString, Log::CRITICAL_ERROR_LEVEL ); } void AppLog::criticalError( const char *inLoggerName, const char *inString ) { mLogPointerWrapper.mLog->logString( inLoggerName, inString, Log::CRITICAL_ERROR_LEVEL ); } void AppLog::error( const char *inString ) { mLogPointerWrapper.mLog->logString( inString, Log::ERROR_LEVEL ); } void AppLog::error( const char *inLoggerName, const char *inString ) { mLogPointerWrapper.mLog->logString( inLoggerName, inString, Log::ERROR_LEVEL ); } void AppLog::warning( const char *inString ) { mLogPointerWrapper.mLog->logString( inString, Log::WARNING_LEVEL ); } void AppLog::warning( const char *inLoggerName, const char *inString ) { mLogPointerWrapper.mLog->logString( inLoggerName, inString, Log::WARNING_LEVEL ); } void AppLog::info( const char *inString ) { mLogPointerWrapper.mLog->logString( inString, Log::INFO_LEVEL ); } void AppLog::info( const char *inLoggerName, const char *inString ) { mLogPointerWrapper.mLog->logString( inLoggerName, inString, Log::INFO_LEVEL ); } void AppLog::detail( const char *inString ) { mLogPointerWrapper.mLog->logString( inString, Log::DETAIL_LEVEL ); } void AppLog::detail( const char *inLoggerName, const char *inString ) { mLogPointerWrapper.mLog->logString( inLoggerName, inString, Log::DETAIL_LEVEL ); } void AppLog::trace( const char *inString ) { mLogPointerWrapper.mLog->logString( inString, Log::TRACE_LEVEL ); } void AppLog::trace( const char *inLoggerName, const char *inString ) { mLogPointerWrapper.mLog->logString( inLoggerName, inString, Log::TRACE_LEVEL ); } void AppLog::setLog( Log *inLog ) { int currentLoggingLevel = getLoggingLevel(); if( inLog != mLogPointerWrapper.mLog ) { delete mLogPointerWrapper.mLog; } mLogPointerWrapper.mLog = inLog; setLoggingLevel( currentLoggingLevel ); } Log *AppLog::getLog() { return mLogPointerWrapper.mLog; } void AppLog::setLoggingLevel( int inLevel ) { mLogPointerWrapper.mLog->setLoggingLevel( inLevel ); } int AppLog::getLoggingLevel() { return mLogPointerWrapper.mLog->getLoggingLevel(); } between-6+dfsg1.orig/minorGems/util/log/Log.cpp0000640000175000017500000000057111435543337020177 0ustar pabspabs/* * Modification History * * 2002-February-25 Jason Rohrer * Created. */ #include "Log.h" const int Log::DEACTIVATE_LEVEL = 0; const int Log::CRITICAL_ERROR_LEVEL = 1; const int Log::ERROR_LEVEL = 2; const int Log::WARNING_LEVEL = 3; const int Log::INFO_LEVEL = 4; const int Log::DETAIL_LEVEL = 5; const int Log::TRACE_LEVEL = 6; Log::~Log() { } between-6+dfsg1.orig/minorGems/util/log/PrintLog.cpp0000640000175000017500000001116611435543337021216 0ustar pabspabs/* * Modification History * * 2002-February-25 Jason Rohrer * Created. * * 2002-March-11 Jason Rohrer * Added a missing include. * * 2002-April-8 Jason Rohrer * Fixed a casting, dereferencing Win32 compile bug. * Changed to be thread-safe. * Changed to use thread-safe printing function. * * 2002-April-8 Jason Rohrer * Fixed a signed-unsigned mismatch. * * 2004-January-11 Jason Rohrer * Added lock around asctime call. * Increased scope of lock. * * 2004-January-29 Jason Rohrer * Changed to use ctime instead of localtime and asctime. * Improved locking scope. * Changed to use autoSprintf. * * 2010-April-5 Jason Rohrer * Printf-like functionality. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ #include "PrintLog.h" #include "minorGems/system/Time.h" #include "minorGems/util/printUtils.h" #include "minorGems/util/stringUtils.h" #include #include #include #include const char *PrintLog::mDefaultLoggerName = "general"; PrintLog::PrintLog() : mLoggingLevel( Log::TRACE_LEVEL ), mLock( new MutexLock() ) { } PrintLog::~PrintLog() { delete mLock; } void PrintLog::setLoggingLevel( int inLevel ) { mLock->lock(); mLoggingLevel = inLevel; mLock->unlock(); } int PrintLog::getLoggingLevel() { mLock->lock(); int level = mLoggingLevel; mLock->unlock(); return level; } void PrintLog::logString( const char *inString, int inLevel ) { logString( (char *)mDefaultLoggerName, inString, inLevel ); } void PrintLog::logString( const char *inLoggerName, const char *inString, int inLevel ) { // not thread-safe to read mLoggingLevel here // without synchronization. // However, we want logging calls that are above // our level to execute with nearly no overhead. // mutex might be too much overhead.... // Besides, not being thread-safe in this case might // (worst case) result in a missed log entry or // an extra log entry... but setting the logging level should be rare. if( inLevel <= mLoggingLevel ) { char *message = generateLogMessage( inLoggerName, inString, inLevel ); threadPrintF( "%s\n", message ); delete [] message; } } void PrintLog::logPrintf( int inLevel, const char* inFormatString, ... ) { unsigned int bufferSize = 200; va_list argList; va_start( argList, inFormatString ); char *buffer = new char[ bufferSize ]; int stringLength = vsnprintf( buffer, bufferSize, inFormatString, argList ); va_end( argList ); if( stringLength == -1 || stringLength >= (int)bufferSize ) { // too long! delete [] buffer; buffer = stringDuplicate( "Message too long" ); } logString( (char *)mDefaultLoggerName, buffer, inLevel ); delete [] buffer; } void PrintLog::logNPrintf( const char *inLoggerName, int inLevel, const char* inFormatString, ... ) { unsigned int bufferSize = 200; va_list argList; va_start( argList, inFormatString ); char *buffer = new char[ bufferSize ]; int stringLength = vsnprintf( buffer, bufferSize, inFormatString, argList ); va_end( argList ); if( stringLength == -1 || stringLength >= (int)bufferSize ) { // too long! delete [] buffer; buffer = stringDuplicate( "Message too long" ); } logString( inLoggerName, buffer, inLevel ); delete [] buffer; } char *PrintLog::generateLogMessage( const char *inLoggerName, const char *inString, int inLevel ) { unsigned long seconds, milliseconds; Time::getCurrentTime( &seconds, &milliseconds ); // lock around ctime call, since it returns a static buffer mLock->lock(); char *dateString = stringDuplicate( ctime( (time_t *)( &seconds ) ) ); // done with static buffer, since we made a copy mLock->unlock(); // this date string ends with a newline... // get rid of it dateString[ strlen(dateString) - 1 ] = '\0'; char *messageBuffer = autoSprintf( "L%d | %s (%ld ms) | %s | %s", inLevel, dateString, milliseconds, inLoggerName, inString ); delete [] dateString; return messageBuffer; } between-6+dfsg1.orig/minorGems/util/log/testLog.cpp0000640000175000017500000000147211435543337021100 0ustar pabspabs/* * Modification History * * 2002-February-25 Jason Rohrer * Created. */ #include "AppLog.h" #include "FileLog.h" #include "Log.h" int main() { AppLog::warning( "A test warning" ); AppLog::warning( "Another test warning" ); AppLog::warning( "mainApp", "And Another test warning" ); AppLog::setLoggingLevel( Log::ERROR_LEVEL ); AppLog::warning( "Yet Another test warning" ); AppLog::error( "mainApp", "A test error" ); AppLog::setLog( new FileLog( "test.log" ) ); // this should be skipped AppLog::warning( "A second test warning" ); // this should not be AppLog::criticalError( "A critical error" ); AppLog::setLog( new FileLog( "test2.log" ) ); // this should be skipped AppLog::warning( "A third test warning" ); return 0; } between-6+dfsg1.orig/minorGems/util/log/Log.h0000640000175000017500000000546311435543337017651 0ustar pabspabs/* * Modification History * * 2002-February-25 Jason Rohrer * Created. * * 2002-March-29 Jason Rohrer * Added Fortify inclusion. * * 2010-April-5 Jason Rohrer * Printf-like functionality. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ #include "minorGems/common.h" #ifndef LOG_INCLUDED #define LOG_INCLUDED #ifdef FORTIFY #include "minorGems/util/development/fortify/fortify.h" #endif /** * An interface for a class that can perform logging functions. * * @author Jason Rohrer */ class Log { public: // These levels were copied from the JLog framework // by Todd Lauinger static const int DEACTIVATE_LEVEL; static const int CRITICAL_ERROR_LEVEL; static const int ERROR_LEVEL; static const int WARNING_LEVEL; static const int INFO_LEVEL; static const int DETAIL_LEVEL; static const int TRACE_LEVEL; // provided so that virtual deletes work properly virtual ~Log(); /** * Sets the logging level of the current log. * * Messages with levels above the current level will not be logged. * * @param inLevel one of the defined logging levels. */ virtual void setLoggingLevel( int inLevel ) = 0; /** * Gets the logging level of the current log. * * Messages with levels above the current level will not be logged. * * @return one of the defined logging levels. */ virtual int getLoggingLevel() = 0; /** * Logs a string in this log under the default logger name. * * @param inString the string to log as a \0-terminated string. * Must be destroyed by caller. * @param inLevel the level to log inString at. */ virtual void logString( const char *inString, int inLevel ) = 0; /** * Logs a string in this log, specifying a logger name. * * @param inLoggerName the name of the logger * as a \0-terminated string. * Must be destroyed by caller. * @param inString the string to log as a \0-terminated string. * Must be destroyed by caller. * @param inLevel the level to log inString at. */ virtual void logString( const char *inLoggerName, const char *inString, int inLevel ) = 0; virtual void logPrintf( int inLevel, const char* inFormatString, ... ) = 0; virtual void logNPrintf( const char *inLoggerName, int inLevel, const char* inFormatString, ... ) = 0; }; #endif between-6+dfsg1.orig/minorGems/util/StringBufferOutputStream.h0000640000175000017500000000277211435543337023344 0ustar pabspabs/* * Modification History * * 2002-August-1 Jason Rohrer * Created. * * 2004-May-9 Jason Rohrer * Added function for getting data as a byte array. */ #include "minorGems/common.h" #ifndef STRING_BUFFER_OUTPUT_STREAM_INCLUDED #define STRING_BUFFER_OUTPUT_STREAM_INCLUDED #include "minorGems/util/SimpleVector.h" #include "minorGems/io/OutputStream.h" /** * An output stream that fills a string buffer. * * @author Jason Rohrer */ class StringBufferOutputStream : public OutputStream { public: StringBufferOutputStream(); ~StringBufferOutputStream(); /** * Gets the data writen to this stream since construction as a * \0-terminated string. * * @return a string containing all data written to this stream. * Must be destroyed by caller. */ char *getString(); /** * Gets the data writen to this stream since construction as a * byte array. * * @param outNumBytes pointer to where the array length should be * returned. * * @return an array containingdata written to this stream. * Must be destroyed by caller. */ unsigned char *getBytes( int *outNumBytes ); // implements the OutputStream interface long write( unsigned char *inBuffer, long inNumBytes ); protected: SimpleVector *mCharacterVector; }; #endif between-6+dfsg1.orig/minorGems/util/TranslationManager.cpp0000640000175000017500000002244111435543337022466 0ustar pabspabs/* * Modification History * * 2004-October-7 Jason Rohrer * Created. * * 2006-February-19 Jason Rohrer * Fixed an inconsistency in memory management. * * 2008-September-17 Jason Rohrer * Support for setting language data directly. * * 2010-March-21 Jason Rohrer * Fixed crash if default language file not found. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ #include "TranslationManager.h" #include #include "minorGems/io/file/File.h" // will be destroyed automatically at program termination TranslationManagerStaticMembers TranslationManager::mStaticMembers; void TranslationManager::setDirectoryName( const char *inName ) { mStaticMembers.setDirectoryAndLanguage( inName, mStaticMembers.mLanguageName ); } char *TranslationManager::getDirectoryName() { return stringDuplicate( mStaticMembers.mDirectoryName ); } char **TranslationManager::getAvailableLanguages( int *outNumLanguages ) { File *languageDirectory = new File( NULL, mStaticMembers.mDirectoryName ); if( languageDirectory->exists() && languageDirectory->isDirectory() ) { int numChildFiles; File **childFiles = languageDirectory->getChildFiles( &numChildFiles ); if( childFiles != NULL ) { SimpleVector *languageNames = new SimpleVector(); for( int i=0; igetFileName(); char *extensionPointer = strstr( name, ".txt" ); if( extensionPointer != NULL ) { // terminate string, cutting off extension extensionPointer[0] = '\0'; languageNames->push_back( stringDuplicate( name ) ); } delete [] name; delete childFiles[i]; } delete [] childFiles; char **returnArray = languageNames->getElementArray(); *outNumLanguages = languageNames->size(); delete languageNames; delete languageDirectory; return returnArray; } } delete languageDirectory; // default, if we didn't return above *outNumLanguages = 0; return new char*[0]; } void TranslationManager::setLanguage( const char *inLanguageName ) { mStaticMembers.setDirectoryAndLanguage( mStaticMembers.mDirectoryName, inLanguageName ); } void TranslationManager::setLanguageData( const char *inData ) { mStaticMembers.setTranslationData( inData ); } const char *TranslationManager::translate( const char *inTranslationKey ) { char *translatedString = NULL; SimpleVector *keys = mStaticMembers.mTranslationKeys; SimpleVector *naturalLanguageStrings = mStaticMembers.mNaturalLanguageStrings; if( keys != NULL ) { int numKeys = keys->size(); for( int i=0; igetElement( i ) ) ) == 0 ) { // keys match translatedString = *( naturalLanguageStrings->getElement( i ) ); } } } if( translatedString == NULL ) { // no translation exists // the translation for this key is the key itself // add it to our translation table char *key = stringDuplicate( inTranslationKey ); char *value = stringDuplicate( inTranslationKey ); keys->push_back( key ); naturalLanguageStrings->push_back( value ); // thus, we return a value from our table, just as if a translation // had existed for this string translatedString = value; } return translatedString; } TranslationManagerStaticMembers::TranslationManagerStaticMembers() : mDirectoryName( NULL ), mLanguageName( NULL ), mTranslationKeys( NULL ), mNaturalLanguageStrings( NULL ) { // default setDirectoryAndLanguage( "languages", "English" ); } TranslationManagerStaticMembers::~TranslationManagerStaticMembers() { if( mDirectoryName != NULL ) { delete [] mDirectoryName; } if( mLanguageName != NULL ) { delete [] mLanguageName; } if( mTranslationKeys != NULL ) { int numKeys = mTranslationKeys->size(); for( int i=0; igetElement( i ) ); } delete mTranslationKeys; } if( mNaturalLanguageStrings != NULL ) { int numKeys = mNaturalLanguageStrings->size(); for( int i=0; igetElement( i ) ); } delete mNaturalLanguageStrings; } } void TranslationManagerStaticMembers::setDirectoryAndLanguage( const char *inDirectoryName, const char *inLanguageName ) { // save temp copies first to allow caller to pass our own members in to us char *tempDirectoryName = stringDuplicate( inDirectoryName ); char *tempLanguageName = stringDuplicate( inLanguageName ); if( mDirectoryName != NULL ) { delete [] mDirectoryName; } if( mLanguageName != NULL ) { delete [] mLanguageName; } mDirectoryName = tempDirectoryName; mLanguageName = tempLanguageName; char dataSet = false; File *directoryFile = new File( NULL, mDirectoryName ); if( directoryFile->exists() && directoryFile->isDirectory() ) { char *languageFileName = autoSprintf( "%s.txt", mLanguageName ); File *languageFile = directoryFile->getChildFile( languageFileName ); delete [] languageFileName; if( languageFile != NULL ) { char *languageData = languageFile->readFileContents(); if( languageData != NULL ) { dataSet = true; setTranslationData( languageData ); delete [] languageData; } delete languageFile; } } delete directoryFile; if( !dataSet ) { // failed to open file... // set blank data to ensure that vectors are created setTranslationData( "" ); } } static inline char *stringSkip( const char *inString, int inNumChars ) { return (char *)( &( inString[ inNumChars ] ) ); } void TranslationManagerStaticMembers::setTranslationData( const char *inData ) { // clear the old translation table if( mTranslationKeys != NULL ) { int numKeys = mTranslationKeys->size(); for( int i=0; igetElement( i ) ); } delete mTranslationKeys; } if( mNaturalLanguageStrings != NULL ) { int numKeys = mNaturalLanguageStrings->size(); for( int i=0; igetElement( i ) ); } delete mNaturalLanguageStrings; } // now read in the translation table mTranslationKeys = new SimpleVector(); mNaturalLanguageStrings = new SimpleVector(); char readError = false; while( ! readError ) { char *key = new char[ 100 ]; int numRead = sscanf( inData, "%99s", key ); if( numRead == 1 ) { inData = stringSkip( inData, strlen( key ) ); // skip the first " int readChar = ' '; while( readChar != '"' && readChar != '\0' ) { readChar = inData[0]; inData = stringSkip( inData, 1 ); } if( readChar != EOF ) { char *naturalLanguageString = new char[1000]; // scan a string of up to 999 characters, stopping // at the first " character numRead = sscanf( inData, "%999[^\"]", naturalLanguageString ); if( numRead == 1 ) { inData = stringSkip( inData, strlen( naturalLanguageString ) ); // trim the key and string and save them mTranslationKeys->push_back( stringDuplicate( key ) ); mNaturalLanguageStrings->push_back( stringDuplicate( naturalLanguageString ) ); } else { readError = true; } delete [] naturalLanguageString; // skip the trailing " readChar = ' '; while( readChar != '"' && readChar != '\0' ) { readChar = inData[0]; inData = stringSkip( inData, 1 ); } } else { readError = true; } } else { readError = true; } delete [] key; } } between-6+dfsg1.orig/minorGems/util/StringBufferOutputStream.cpp0000640000175000017500000000227411435543337023674 0ustar pabspabs/* * Modification History * * 2002-August-1 Jason Rohrer * Created. * * 2004-May-9 Jason Rohrer * Added function for getting data as a byte array. */ #include "minorGems/util/StringBufferOutputStream.h" StringBufferOutputStream::StringBufferOutputStream() : mCharacterVector( new SimpleVector() ) { } StringBufferOutputStream::~StringBufferOutputStream() { delete mCharacterVector; } char *StringBufferOutputStream::getString() { int numChars = mCharacterVector->size(); char *returnArray = new char[ numChars + 1 ]; for( int i=0; igetElement( i ) ) ); } returnArray[ numChars ] = '\0'; return returnArray; } unsigned char *StringBufferOutputStream::getBytes( int *outNumBytes ) { *outNumBytes = mCharacterVector->size(); return mCharacterVector->getElementArray(); } long StringBufferOutputStream::write( unsigned char *inBuffer, long inNumBytes ) { for( int i=0; ipush_back( inBuffer[ i ] ); } return inNumBytes; } between-6+dfsg1.orig/minorGems/util/stringUtils.cpp0000640000175000017500000002625711435543340021227 0ustar pabspabs/* * Modification History * * 2003-May-10 Jason Rohrer * Created. * Added a tokenization function. * * 2003-June-14 Jason Rohrer * Added a join function. * * 2003-June-22 Jason Rohrer * Added an autoSprintf function. * * 2003-July-27 Jason Rohrer * Fixed bugs in autoSprintf return values for certain cases. * * 2003-August-12 Jason Rohrer * Added a concatonate function. * * 2003-September-7 Jason Rohrer * Changed so that split returns last part, even if it is empty. * * 2004-January-15 Jason Rohrer * Added work-around for MinGW vsnprintf bug. * * 2006-June-2 Jason Rohrer * Added a stringStartsWith function. * * 2009-September-7 Jason Rohrer * Fixed int types. * Switched away from StringBufferOutputStream to new function in SimpleVector. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ #include "stringUtils.h" #include char *stringToLowerCase( const char *inString ) { unsigned int length = strlen( inString ); char *returnString = stringDuplicate( inString ); for( unsigned int i=0; i stringLength ) { return false; } else { for( unsigned int i=0; i *parts = new SimpleVector(); char *workingString = stringDuplicate( inString ); char *workingStart = workingString; unsigned int separatorLength = strlen( inSeparator ); char *foundSeparator = strstr( workingString, inSeparator ); while( foundSeparator != NULL ) { // terminate at separator foundSeparator[0] = '\0'; parts->push_back( stringDuplicate( workingString ) ); // skip separator workingString = &( foundSeparator[ separatorLength ] ); foundSeparator = strstr( workingString, inSeparator ); } // add the remaining part, even if it is the empty string parts->push_back( stringDuplicate( workingString ) ); delete [] workingStart; *outNumParts = parts->size(); char **returnArray = parts->getElementArray(); delete parts; return returnArray; } char *join( char **inStrings, int inNumParts, const char *inGlue ) { SimpleVector result; for( int i=0; i *inTargetVector, SimpleVector *inSubstituteVector ) { int numTargets = inTargetVector->size(); char *newHaystack = stringDuplicate( inHaystack ); char tagFound; for( int i=0; igetElement( i ) ), *( inSubstituteVector->getElement( i ) ), &tagFound ); delete [] newHaystack; newHaystack = newHaystackWithReplacements; } return newHaystack; } SimpleVector *tokenizeString( const char *inString ) { char *tempString = stringDuplicate( inString ); char *restOfString = tempString; SimpleVector *foundTokens = new SimpleVector(); SimpleVector *currentToken = new SimpleVector(); while( restOfString[0] != '\0' ) { // characters remain // skip whitespace char nextChar = restOfString[0]; while( nextChar == ' ' || nextChar == '\n' || nextChar == '\r' || nextChar == '\t' ) { restOfString = &( restOfString[1] ); nextChar = restOfString[0]; } if( restOfString[0] != '\0' ) { // a token while( nextChar != ' ' && nextChar != '\n' && nextChar != '\r' && nextChar != '\t' && nextChar != '\0' ) { // still not whitespace currentToken->push_back( nextChar ); restOfString = &( restOfString[1] ); nextChar = restOfString[0]; } // reached end of token foundTokens->push_back( currentToken->getElementString() ); currentToken->deleteAll(); } } delete [] tempString; delete currentToken; return foundTokens; } char *autoSprintf( const char* inFormatString, ... ) { unsigned int bufferSize = 50; va_list argList; va_start( argList, inFormatString ); char *buffer = new char[ bufferSize ]; int stringLength = vsnprintf( buffer, bufferSize, inFormatString, argList ); va_end( argList ); if( stringLength != -1 ) { // follows C99 standard... // stringLength is the length of the string that would have been // written if the buffer was big enough // not room for string and terminating \0 in bufferSize bytes if( (unsigned int)stringLength >= bufferSize ) { // need to reprint with a bigger buffer delete [] buffer; bufferSize = (unsigned int)( stringLength + 1 ); va_list argList; va_start( argList, inFormatString ); buffer = new char[ bufferSize ]; // can simply use vsprintf now vsprintf( buffer, inFormatString, argList ); va_end( argList ); return buffer; } else { // buffer was big enough // trim the buffer to fit the string char *returnString = stringDuplicate( buffer ); delete [] buffer; return returnString; } } else { // follows old ANSI standard // -1 means the buffer was too small // Note that some buggy non-C99 vsnprintf implementations // (notably MinGW) // do not return -1 if stringLength equals bufferSize (in other words, // if there is not enough room for the trailing \0). // Thus, we need to check for both // (A) stringLength == -1 // (B) stringLength == bufferSize // below. // keep doubling buffer size until it's big enough while( stringLength == -1 || (unsigned int)stringLength == bufferSize ) { delete [] buffer; if( (unsigned int)stringLength == bufferSize ) { // only occurs if vsnprintf implementation is buggy // might as well use the information, though // (instead of doubling the buffer size again) bufferSize = bufferSize + 1; } else { // double buffer size again bufferSize = 2 * bufferSize; } va_list argList; va_start( argList, inFormatString ); buffer = new char[ bufferSize ]; stringLength = vsnprintf( buffer, bufferSize, inFormatString, argList ); va_end( argList ); } // trim the buffer to fit the string char *returnString = stringDuplicate( buffer ); delete [] buffer; return returnString; } } between-6+dfsg1.orig/minorGems/util/SimpleVector.h0000640000175000017500000002702111435543337020755 0ustar pabspabs// Jason Rohrer // SimpleVector.h /** * * Simple vector template class. Supports pushing at end and random-access deletions. * Dynamically sized. * * * Created 10-24-99 * Mods: * Jason Rohrer 12-11-99 Added deleteAll function * Jason Rohrer 1-30-2000 Changed to return NULL if get called on non-existent element * Jason Rohrer 12-20-2000 Added a function for deleting a particular * element. * Jason Rohrer 12-14-2001 Added a function for getting the index of * a particular element. * Jason Rohrer 1-24-2003 Added a functions for getting an array or * string of all elements. * Jason Rohrer 7-26-2005 Added template <> to explicitly specialized * getElementString. * Jason Rohrer 1-9-2009 Added setElementString method. * Jason Rohrer 9-7-2009 Fixed int types. * Added appendElementString. * Jason Rohrer 11-11-2009 Changed second deleteElement to allow * SimpleVectors containing ints. * Jason Rohrer 12-23-2009 New push_back for arrays. * Jason Rohrer 1-5-2010 Reduced default size to conserve memory. * Jason Rohrer 1-12-2010 Added copy constructor and assignment * operator. * Jason Rohrer 1-16-2010 Fixed bugs in new constructor/operator. * Jason Rohrer 1-18-2010 Fixed memmove/memcpy bugs. * Jason Rohrer 1-28-2010 Data protected for subclass access. * Jason Rohrer 4-28-2010 Fast version of getElement. * Jason Rohrer 5-14-2010 String parameters as const to fix warnings. */ #include "minorGems/common.h" #ifndef SIMPLEVECTOR_INCLUDED #define SIMPLEVECTOR_INCLUDED #include // for memory moving functions const int defaultStartSize = 2; template class SimpleVector { public: SimpleVector(); // create an empty vector SimpleVector(int sizeEstimate); // create an empty vector with a size estimate ~SimpleVector(); // copy constructor SimpleVector( const SimpleVector &inCopy ); // assignment operator SimpleVector & operator = (const SimpleVector &inOther ); void push_back(Type x); // add x to the end of the vector // add array of elements to the end of the vector void push_back(Type *inArray, int inLength); Type *getElement(int index); // get a ptr to element at index in vector Type *getElementFast(int index); // no bounds checking int size(); // return the number of allocated elements in the vector bool deleteElement(int index); // delete element at an index in vector /** * Deletes a particular element. Deletes the first element * in vector == to inElement. * * @param inElement the element to delete. * * @return true iff an element was deleted. */ bool deleteElementEqualTo( Type inElement ); /** * Gets the index of a particular element. Gets the index of the * first element in vector == to inElement. * * @param inElement the element to get the index of. * * @return the index if inElement, or -1 if inElement is not found. */ int getElementIndex( Type inElement ); void deleteAll(); // delete all elements from vector /** * Gets the elements as an array. * * @return the a new array containing all elements in this vector. * Must be destroyed by caller, though elements themselves are * not copied. */ Type *getElementArray(); /** * Gets the char elements as a \0-terminated string. * * @return a \0-terminated string containing all elements in this * vector. * Must be destroyed by caller. */ char *getElementString(); /** * Sets the char elements as a \0-terminated string. * * @param inString a \0-terminated string containing all elements to * set this vector with. * Must be destroyed by caller. */ void setElementString( const char *inString ); /** * Appends chars from a \0-terminated string. * * @param inString a \0-terminated string containing all elements to * append to this vector. * Must be destroyed by caller. */ void appendElementString( const char *inString ); protected: Type *elements; int numFilledElements; int maxSize; int minSize; // number of allocated elements when vector is empty }; template inline SimpleVector::SimpleVector() { elements = new Type[defaultStartSize]; numFilledElements = 0; maxSize = defaultStartSize; minSize = defaultStartSize; } template inline SimpleVector::SimpleVector(int sizeEstimate) { elements = new Type[sizeEstimate]; numFilledElements = 0; maxSize = sizeEstimate; minSize = sizeEstimate; } template inline SimpleVector::~SimpleVector() { delete [] elements; } // copy constructor template inline SimpleVector::SimpleVector( const SimpleVector &inCopy ) : elements( new Type[ inCopy.maxSize ] ), numFilledElements( inCopy.numFilledElements ), maxSize( inCopy.maxSize ), minSize( inCopy.minSize ) { // if these objects contain pointers to stack, etc, this is not // going to work (not a deep copy) // because it won't invoke the copy constructors of the objects! //memcpy( elements, inCopy.elements, sizeof( Type ) * numFilledElements ); for( int i=0; i inline SimpleVector & SimpleVector::operator = ( const SimpleVector &inOther ) { // pattern found on wikipedia: // avoid self-assignment if( this != &inOther ) { // 1: allocate new memory and copy the elements Type *newElements = new Type[ inOther.maxSize ]; // again, memcpy doesn't work here, because it doesn't invoke // copy constructor on contained object /*memcpy( newElements, inOther.elements, sizeof( Type ) * inOther.numFilledElements ); */ for( int i=0; i inline int SimpleVector::size() { return numFilledElements; } template inline Type *SimpleVector::getElement(int index) { if( index < numFilledElements && index >=0 ) { return &(elements[index]); } else return NULL; } template inline Type *SimpleVector::getElementFast(int index) { return &(elements[index]); } template inline bool SimpleVector::deleteElement(int index) { if( index < numFilledElements) { // if index valid for this vector if( index != numFilledElements - 1) { // this spot somewhere in middle // memmove NOT okay here, because it leaves shallow copies // behind that cause errors when the whole element array is // destroyed. /* // move memory towards front by one spot int sizeOfElement = sizeof(Type); int numBytesToMove = sizeOfElement*(numFilledElements - (index+1)); Type *destPtr = &(elements[index]); Type *srcPtr = &(elements[index+1]); memmove( (void *)destPtr, (void *)srcPtr, (unsigned int)numBytesToMove); */ for( int i=index+1; i inline bool SimpleVector::deleteElementEqualTo( Type inElement ) { int index = getElementIndex( inElement ); if( index != -1 ) { return deleteElement( index ); } else { return false; } } template inline int SimpleVector::getElementIndex( Type inElement ) { // walk through vector, looking for first match. for( int i=0; i inline void SimpleVector::deleteAll() { numFilledElements = 0; if( maxSize > minSize ) { // free memory if vector has grown delete [] elements; elements = new Type[minSize]; // reallocate an empty vector maxSize = minSize; } } template inline void SimpleVector::push_back(Type x) { if( numFilledElements < maxSize) { // still room in vector elements[numFilledElements] = x; numFilledElements++; } else { // need to allocate more space for vector int newMaxSize = maxSize << 1; // double size // NOTE: memcpy does not work here, because it does not invoke // copy constructors on elements. // And then "delete []" below causes destructors to be invoked // on old elements, which are shallow copies of new objects. Type *newAlloc = new Type[newMaxSize]; /* unsigned int sizeOfElement = sizeof(Type); unsigned int numBytesToMove = sizeOfElement*(numFilledElements); // move into new space memcpy((void *)newAlloc, (void *) elements, numBytesToMove); */ // must use element-by-element assignment to invoke constructors for( int i=0; i inline void SimpleVector::push_back(Type *inArray, int inLength) { for( int i=0; i inline Type *SimpleVector::getElementArray() { Type *newAlloc = new Type[ numFilledElements ]; // shallow copy not good enough! /* unsigned int sizeOfElement = sizeof( Type ); unsigned int numBytesToCopy = sizeOfElement * numFilledElements; // copy into new space //memcpy( (void *)newAlloc, (void *)elements, numBytesToCopy ); */ // use assignment to ensure that constructors are invoked on element copies for( int i=0; i inline char *SimpleVector::getElementString() { char *newAlloc = new char[ numFilledElements + 1 ]; unsigned int sizeOfElement = sizeof( char ); unsigned int numBytesToCopy = sizeOfElement * numFilledElements; // memcpy fine here, since shallow copy good enough for chars // copy into new space memcpy( (void *)newAlloc, (void *)elements, numBytesToCopy ); newAlloc[ numFilledElements ] = '\0'; return newAlloc; } template <> inline void SimpleVector::appendElementString( const char *inString ) { // slow but correct unsigned int numChars = strlen( inString ); for( unsigned int i=0; i inline void SimpleVector::setElementString( const char *inString ) { deleteAll(); appendElementString( inString ); } #endif between-6+dfsg1.orig/minorGems/util/TranslationManager.h0000640000175000017500000001217311435543337022134 0ustar pabspabs/* * Modification History * * 2004-October-7 Jason Rohrer * Created. * Copied structure from SettingsManager. * * 2006-February-19 Jason Rohrer * Fixed an inconsistency in memory management. * * 2008-September-17 Jason Rohrer * Support for setting language data directly. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ #include "minorGems/common.h" #ifndef TRANSLATION_MANAGER_INCLUDED #define TRANSLATION_MANAGER_INCLUDED #include "minorGems/util/SimpleVector.h" // utility class for dealing with static member dealocation class TranslationManagerStaticMembers; /** * Class that manages natural language translation of user interface strings. * * @author Jason Rohrer */ class TranslationManager { public: /** * Sets the directory name where translation files are stored. * Defaults to "languages". * * @param inName the name of the directory (relative to the * program's working directory). * Must be destroyed by caller. */ static void setDirectoryName( const char *inName ); /** * Gets the directory name where translation files are stored. * * @return the name of the directory (relative to the * program's working directory). * Must be destroyed by caller. */ static char *getDirectoryName(); /** * Gets a list of available languages. * * @param outNumLanguages pointer to where the number of languages * should be returned. * * @return an array of language names. * Array and the strings it contains must be destroyed by caller. */ static char **getAvailableLanguages( int *outNumLanguages ); /** * Sets the natural language to translate keys into. * Defaults to "English". * * @param inLanguageName the name of the language. * This name, when .txt is appended, is the name of * the translation file. Thus, setLanguage( "English" ) would * select the English.txt language file. * Language names must not contain spaces. * Must be destroyed by caller. */ static void setLanguage( const char *inLanguageName ); // Sets the language data directly without reading it from // the file system. // Data string formated the same as a language file. // Data string destroyed by caller static void setLanguageData( const char *inData ); /** * Gets the natural language translation of a key. * * NOTE: if a translation does not exist for the key, the key * itself will be returned. (A copy of the key is returned, so * the original key passed in to translate can be destroyed by caller * if needed). * * @param inTranslationKey the translation key string. * Must be destroyed by caller if non-const. * * @return the translated natural language string. * The string MUST NOT be destroyed by the caller, as it will * be destroyed by this class upon program termination. * * This specification allows the translate function to be used * inline, whether or not a correct translation exists. Thus
         *
         * printf( "%s", translate( myKey ) );
         * delete [] myKey;
         * 
* * will always be correct, whether or not a translation exists, as * will
         *
         * printf( "%s", translate( "MY_KEY" ) );
         * 
*/ static const char *translate( const char *inTranslationKey ); protected: static TranslationManagerStaticMembers mStaticMembers; }; /** * Container for static members to allow for their proper destruction * on program termination. * * @author Jason Rohrer */ class TranslationManagerStaticMembers { public: TranslationManagerStaticMembers(); ~TranslationManagerStaticMembers(); /** * Sets the directory name and language name to use, and reads * the translation table from file. * * @param inDirectoryName the directory name. * Must be destroyed by caller. * @param inLanguageName the language name. * Must be destroyed by caller. */ void setDirectoryAndLanguage( const char *inDirectoryName, const char *inLanguageName ); // sets the data from a string // string contains same contents as a language file // string destroyed by caller void setTranslationData( const char *inData ); char *mDirectoryName; char *mLanguageName; // vectors mapping keys to strings SimpleVector *mTranslationKeys; SimpleVector *mNaturalLanguageStrings; }; #endif between-6+dfsg1.orig/minorGems/util/printUtils.h0000640000175000017500000000102711435543337020514 0ustar pabspabs/* * Modification History * * 2002-April-8 Jason Rohrer * Created. */ #include "minorGems/common.h" #ifndef PRINT_UTILS_INCLUDED #define PRINT_UTILS_INCLUDED /** * A thread-safe version of printf. * * Note that printf is already thread-safe on certain platforms, * but does not seem to be thread-safe on Win32. * * @param inFormatString the format string to use. * @param ... a variable argument list, with the same usage * pattern as printf. */ int threadPrintF( const char* inFormatString, ... ); #endif between-6+dfsg1.orig/minorGems/util/printUtils.cpp0000640000175000017500000000107411435543337021051 0ustar pabspabs/* * Modification History * * 2002-April-8 Jason Rohrer * Created. * * 2002-April-11 Jason Rohrer * Added a missing return value. */ #include "printUtils.h" #include "minorGems/system/MutexLock.h" #include // for variable argument lists #include MutexLock threadPrintFLock; int threadPrintF( const char* inFormatString, ... ) { threadPrintFLock.lock(); va_list argList; va_start( argList, inFormatString ); int returnVal = vprintf( inFormatString, argList ); threadPrintFLock.unlock(); return returnVal; } between-6+dfsg1.orig/minorGems/util/test/0000750000175000017500000000000011435543340017136 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/util/test/testSnprintf.mingw.out0000640000175000017500000000055611435543340023521 0ustar pabspabsPrinted string of length 3 to buffer of size 4 with snprintf. Return value = 3 Buffer was null-terminated by snprintf Printed string of length 4 to buffer of size 4 with snprintf. Return value = 4 Buffer was NOT null-terminated by snprintf Printed string of length 5 to buffer of size 4 with snprintf. Return value = -1 Buffer was NOT null-terminated by snprintf between-6+dfsg1.orig/minorGems/util/test/testSnprintf.cpp0000640000175000017500000000232411435543340022347 0ustar pabspabs/* * Modification History * * 2004-January-15 Jason Rohrer * Created. */ /** * A test program for snprintf behavior. */ #include #include #include int main() { int numStrings = 3; // test strings of length 3, 4, and 5 const char *testStrings[3] = { "tst", "test", "testt" }; int result; // a buffer of length 4, which IS NOT large // enough to hold the last two testStrings char *buffer = (char*)( malloc( 4 ) ); int i; for( i=0; i * * Modified by Aaron D. Gifford * * NO COPYRIGHT - THIS IS 100% IN THE PUBLIC DOMAIN * * The original unmodified version is available at: * ftp://ftp.funet.fi/pub/crypt/hash/sha/sha1.c * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "sha1.h" #include #include // for hex encoding #include "minorGems/formats/encodingUtils.h" #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) /* blk0() and blk() perform the initial expand. */ /* I got the idea of expanding during the round function from SSLeay */ #if __BYTE_ORDER == __LITTLE_ENDIAN #define blk0(i) (block->l[i] = (rol(block->l[i],24)&(sha1_quadbyte)0xFF00FF00) \ |(rol(block->l[i],8)&(sha1_quadbyte)0x00FF00FF)) #else #define blk0(i) block->l[i] #endif #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ ^block->l[(i+2)&15]^block->l[i&15],1)) /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); typedef union _BYTE64QUAD16 { sha1_byte c[64]; sha1_quadbyte l[16]; } BYTE64QUAD16; /* Hash a single 512-bit block. This is the core of the algorithm. */ void SHA1_Transform(sha1_quadbyte state[5], sha1_byte buffer[64]) { sha1_quadbyte a, b, c, d, e; BYTE64QUAD16 *block; block = (BYTE64QUAD16*)buffer; /* Copy context->state[] to working vars */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; /* 4 rounds of 20 operations each. Loop unrolled. */ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); /* Add the working vars back into context.state[] */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; /* Wipe variables */ a = b = c = d = e = 0; } /* SHA1_Init - Initialize new context */ void SHA1_Init(SHA_CTX* context) { /* SHA1 initialization constants */ context->state[0] = 0x67452301; context->state[1] = 0xEFCDAB89; context->state[2] = 0x98BADCFE; context->state[3] = 0x10325476; context->state[4] = 0xC3D2E1F0; context->count[0] = context->count[1] = 0; } /* Run your data through this. */ void SHA1_Update(SHA_CTX *context, sha1_byte *data, unsigned int len) { unsigned int i, j; j = (context->count[0] >> 3) & 63; if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; context->count[1] += (len >> 29); if ((j + len) > 63) { memcpy(&context->buffer[j], data, (i = 64-j)); SHA1_Transform(context->state, context->buffer); for ( ; i + 63 < len; i += 64) { SHA1_Transform(context->state, &data[i]); } j = 0; } else i = 0; memcpy(&context->buffer[j], &data[i], len - i); } /* Add padding and return the message digest. */ void SHA1_Final(sha1_byte digest[SHA1_DIGEST_LENGTH], SHA_CTX *context) { sha1_quadbyte i, j; sha1_byte finalcount[8]; for (i = 0; i < 8; i++) { finalcount[i] = (sha1_byte)((context->count[(i >= 4 ? 0 : 1)] >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ } SHA1_Update(context, (sha1_byte *)"\200", 1); while ((context->count[0] & 504) != 448) { SHA1_Update(context, (sha1_byte *)"\0", 1); } /* Should cause a SHA1_Transform() */ SHA1_Update(context, finalcount, 8); for (i = 0; i < SHA1_DIGEST_LENGTH; i++) { digest[i] = (sha1_byte) ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); } /* Wipe variables */ i = j = 0; memset(context->buffer, 0, SHA1_BLOCK_LENGTH); memset(context->state, 0, SHA1_DIGEST_LENGTH); memset(context->count, 0, 8); memset(&finalcount, 0, 8); } unsigned char *computeRawSHA1Digest( unsigned char *inData, int inDataLength ) { SHA_CTX context; SHA1_Init( &context ); // copy into buffer, since this SHA1 implementation seems to overwrite // parts of the data buffer. unsigned char *buffer = new unsigned char[ inDataLength ]; memcpy( (void *)buffer, (void *)inData, inDataLength ); SHA1_Update( &context, buffer, inDataLength ); delete [] buffer; unsigned char *digest = new unsigned char[ SHA1_DIGEST_LENGTH ]; SHA1_Final( digest, &context ); return digest; } unsigned char *computeRawSHA1Digest( char *inString ) { SHA_CTX context; SHA1_Init( &context ); // copy into buffer, since this SHA1 implementation seems to overwrite // parts of the data buffer. int dataLength = strlen( inString ); unsigned char *buffer = new unsigned char[ dataLength ]; memcpy( (void *)buffer, (void *)inString, dataLength ); SHA1_Update( &context, buffer, strlen( inString ) ); delete [] buffer; unsigned char *digest = new unsigned char[ SHA1_DIGEST_LENGTH ]; SHA1_Final( digest, &context ); return digest; } char *computeSHA1Digest( char *inString ) { unsigned char *digest = computeRawSHA1Digest( inString ); char *digestHexString = hexEncode( digest, SHA1_DIGEST_LENGTH ); delete [] digest; return digestHexString; } char *computeSHA1Digest( unsigned char *inData, int inDataLength ) { unsigned char *digest = computeRawSHA1Digest( inData, inDataLength ); char *digestHexString = hexEncode( digest, SHA1_DIGEST_LENGTH ); delete [] digest; return digestHexString; } between-6+dfsg1.orig/minorGems/crypto/hashes/sha1sumCompile0000750000175000017500000000011611435543333022615 0ustar pabspabsg++ -I../../.. -o sha1sum sha1sum.cpp sha1.cpp ../../formats/encodingUtils.cppbetween-6+dfsg1.orig/minorGems/crypto/hashes/sha1sum.cpp0000640000175000017500000000356111435543333022072 0ustar pabspabs/* * Modification History * * 2004-May-20 Jason Rohrer * Created. */ #include "sha1.h" #include "minorGems/formats/encodingUtils.h" #include #include /** * Prints usage message and exits. * * @param inAppName the name of the app. */ void usage( char *inAppName ); int main( int inNumArgs, char **inArgs ) { if( inNumArgs != 2 ) { usage( inArgs[0] ); } FILE *file = fopen( inArgs[1], "rb" ); if( file == NULL ) { printf( "Failed to open file %s for reading\n\n", inArgs[1] ); usage( inArgs[0] ); } SHA_CTX shaContext; SHA1_Init( &shaContext ); int bufferSize = 5000; unsigned char *buffer = new unsigned char[ bufferSize ]; int numRead = bufferSize; char error = false; // read bytes from file until we run out while( numRead == bufferSize && !error ) { numRead = fread( buffer, 1, bufferSize, file ); if( numRead > 0 ) { SHA1_Update( &shaContext, buffer, numRead ); } else{ error = true; } } fclose( file ); delete [] buffer; if( error ) { printf( "Error reading from file %s\n", inArgs[1] ); } else { unsigned char *rawDigest = new unsigned char[ SHA1_DIGEST_LENGTH ]; SHA1_Final( rawDigest, &shaContext ); // else hash is correct char *digestHexString = hexEncode( rawDigest, SHA1_DIGEST_LENGTH ); printf( "%s %s\n", digestHexString, inArgs[1] ); delete [] rawDigest; delete [] digestHexString; } return 0; } void usage( char *inAppName ) { printf( "Usage:\n\n" ); printf( "\t%s file_to_sum\n", inAppName ); printf( "example:\n" ); printf( "\t%s test.txt\n", inAppName ); exit( 1 ); } between-6+dfsg1.orig/minorGems/crypto/hashes/sha1.h0000640000175000017500000000765711435543333021024 0ustar pabspabs/* * Modification History * * 2002-May-25 Jason Rohrer * Changed to use minorGems endian.h * Added a function for hashing an entire string to a hex digest. * Added a function for getting a raw digest. * * 2003-September-15 Jason Rohrer * Added support for hashing raw (non-string) data. * Removed legacy C code. */ /* * sha.h * * Originally taken from the public domain SHA1 implementation * written by by Steve Reid * * Modified by Aaron D. Gifford * * NO COPYRIGHT - THIS IS 100% IN THE PUBLIC DOMAIN * * The original unmodified version is available at: * ftp://ftp.funet.fi/pub/crypt/hash/sha/sha1.c * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef __SHA1_H__ #define __SHA1_H__ #include "minorGems/system/endian.h" /* Make sure you define these types for your architecture: */ typedef unsigned int sha1_quadbyte; /* 4 byte type */ typedef unsigned char sha1_byte; /* single byte type */ /* * Be sure to get the above definitions right. For instance, on my * x86 based FreeBSD box, I define LITTLE_ENDIAN and use the type * "unsigned long" for the quadbyte. On FreeBSD on the Alpha, however, * while I still use LITTLE_ENDIAN, I must define the quadbyte type * as "unsigned int" instead. */ #define SHA1_BLOCK_LENGTH 64 #define SHA1_DIGEST_LENGTH 20 /* The SHA1 structure: */ typedef struct _SHA_CTX { sha1_quadbyte state[5]; sha1_quadbyte count[2]; sha1_byte buffer[SHA1_BLOCK_LENGTH]; } SHA_CTX; // BIG NOTE: // These overwrite the data! // copy your data to a temporary buffer before passing it through // (the "nicer" functions below these 3 do not overwrite data) void SHA1_Init(SHA_CTX *context); void SHA1_Update(SHA_CTX *context, sha1_byte *data, unsigned int len); void SHA1_Final(sha1_byte digest[SHA1_DIGEST_LENGTH], SHA_CTX* context); /** * Computes a unencoded 20-byte digest from data. * * @param inData the data to hash. * Must be destroyed by caller. * @param inDataLength the length of the data to hash. * Must be destroyed by caller. * * @return the digest as a byte array of length 20. * Must be destroyed by caller. */ unsigned char *computeRawSHA1Digest( unsigned char *inData, int inDataLength ); /** * Computes a unencoded 20-byte digest from an arbitrary string message. * * @param inString the message as a \0-terminated string. * Must be destroyed by caller. * * @return the digest as a byte array of length 20. * Must be destroyed by caller. */ unsigned char *computeRawSHA1Digest( char *inString ); /** * Computes a hex-encoded string digest from data. * * @param inData the data to hash. * Must be destroyed by caller. * @param inDataLength the length of the data to hash. * Must be destroyed by caller. * * @return the digest as a \0-terminated string. * Must be destroyed by caller. */ char *computeSHA1Digest( unsigned char *inData, int inDataLength ); /** * Computes a hex-encoded string digest from an arbitrary string message. * * @param inString the message as a \0-terminated string. * Must be destroyed by caller. * * @return the digest as a \0-terminated string. * Must be destroyed by caller. */ char *computeSHA1Digest( char *inString ); #endif between-6+dfsg1.orig/minorGems/crypto/hashes/sha1Test.cpp0000640000175000017500000000476711435543333022216 0ustar pabspabs/* * Modification History * * 2002-May-25 Jason Rohrer * Created. * * 2003-September-21 Jason Rohrer * Added test of long string. */ #include "sha1.h" #include #include /** * All parameters must be destroyed by caller. */ void checkHash( char *inString, char *inTestName, char *inCorrectHash ); int main() { /* * Test vectors: * * "abc" * A999 3E36 4706 816A BA3E 2571 7850 C26C 9CD0 D89D * * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" * 8498 3E44 1C3B D26E BAAE 4AA1 F951 29E5 E546 70F1 * * A million repetitions of "a" * 34AA 973C D4C4 DAA4 F61E EB2B DBAD 2731 6534 016F */ char *abc = "abc"; char *correctABCHash = "A9993E364706816ABA3E25717850C26C9CD0D89D"; char *mixedAlpha = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; char *correctMixedAlphaHash = "84983E441C3BD26EBAAE4AA1F95129E5E54670F1"; char *correctMillionHash = "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F"; int oneMillion = 1000000; char *millionAs = new char[ oneMillion + 1 ]; for( int i=0; i getKeyDown( int vKeyCode ) { return ((GetAsyncKeyState(vKeyCode) & 0x8000) ? true : false); } getKeyUp( int vKeyCode ) { return ((GetAsyncKeyState(vKeyCode) & 0x8000) ? false : true); } Sample Mac implementation #include getKeyDown( int vKeyCode ) { KeyMapByteArray keyArray; GetKeys( keyArray ); int arrayInd = vKeyCode >> 3; // divide by 8 to get start array index of key code unsigned char neededByte = keyArray[ arrayInd ]; return (neededByte >> vKeyCode % 8) && 0x01; // trim off bit needed } getKeyUp( int vKeyCode ) { KeyMapByteArray keyArray; GetKeys( keyArray ); int arrayInd = vKeyCode >> 3; // divide by 8 to get start array index of key code unsigned char neededByte = keyArray[ arrayInd ]; return !((neededByte >> vKeyCode % 8) && 0x01); // trim off bit needed, and invert } */between-6+dfsg1.orig/minorGems/graphics/filters/0000750000175000017500000000000011435543334020455 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/graphics/filters/InvertFilter.h0000640000175000017500000000123311435543334023243 0ustar pabspabs/* * Modification History * * 2000-December-21 Jason Rohrer * Created. */ #ifndef INVERT_FILTER_INCLUDED #define INVERT_FILTER_INCLUDED #include "minorGems/graphics/ChannelFilter.h" /** * Filter that inverts the values in a channel. * * @author Jason Rohrer */ class InvertFilter : public ChannelFilter { public: // implements the ChannelFilter interface void apply( double *inChannel, int inWidth, int inHeight ); }; inline void InvertFilter::apply( double *inChannel, int inWidth, int inHeight ) { int numPixels = inWidth * inHeight; for( int i=0; i *mFilterVector; }; inline MultiFilter::MultiFilter() : mFilterVector( new SimpleVector() ) { } inline MultiFilter::~MultiFilter() { delete mFilterVector; } inline void MultiFilter::apply( double *inChannel, int inWidth, int inHeight ) { int numFilters = mFilterVector->size(); for( int i=0; igetElement( i ) ); thisFilter->apply( inChannel, inWidth, inHeight ); } } #endif between-6+dfsg1.orig/minorGems/graphics/filters/MedianFilter.h0000640000175000017500000000672411435543334023203 0ustar pabspabs/* * Modification History * * 2001-May-15 Jeremy Tavan * Created. * * 2001-May-16 Jeremy Tavan * Modified to use the much faster quick_select * median-finding algorithm. * * 2001-May-17 Jaosn Rohrer * Tried to optimize by moving stuff out of the inner-inner loop. * It helped a bit, but not much. * */ #ifndef MEDIAN_FILTER_INCLUDED #define MEDIAN_FILTER_INCLUDED #include "minorGems/graphics/ChannelFilter.h" #include "quickselect.h" int medianFilterCompareInt( const void *x, const void *y ); /** * Median convolution filter. * * @author Jeremy Tavan */ class MedianFilter : public ChannelFilter { public: /** * Constructs a median filter. * * @param inRadius the radius of the box in pixels. */ MedianFilter( int inRadius ); /** * Sets the box radius. * * @param inRadius the radius of the box in pixels. */ void setRadius( int inRadius ); /** * Gets the box radius. * * @return the radius of the box in pixels. */ int getRadius(); // implements the ChannelFilter interface void apply( double *inChannel, int inWidth, int inHeight ); private: int mRadius; }; inline MedianFilter::MedianFilter( int inRadius ) : mRadius( inRadius ) { } inline void MedianFilter::setRadius( int inRadius ) { mRadius = inRadius; } inline int MedianFilter::getRadius() { return mRadius; } inline void MedianFilter::apply( double *inChannel, int inWidth, int inHeight ) { // pre-compute an integer version of the channel for the // median alg to use int numPixels = inWidth * inHeight; int *intChannel = new int[ numPixels ]; for( int p=0; p= inHeight ) { endBoxY = inHeight - 1; } int boxSizeY = endBoxY - startBoxY + 1; for( int x=0; x= inWidth ) { endBoxX = inWidth - 1; } int boxSizeX = endBoxX - startBoxX + 1; int *buffer = new int[boxSizeX * boxSizeY]; // sum all pixels in the box around this pixel for( int boxY = startBoxY; boxY<=endBoxY; boxY++ ) { int yBoxIndexContrib = boxY * inWidth; int yBoxContrib = boxSizeX * ( boxY-startBoxY ); for( int boxX = startBoxX; boxX<=endBoxX; boxX++ ) { //buffer[boxSizeX*(boxY-startBoxY)+(boxX-startBoxX)] = (int)(1000.0 * inChannel[yBoxIndexContrib + boxX]); buffer[ yBoxContrib + ( boxX-startBoxX ) ] = intChannel[ yBoxIndexContrib + boxX ]; } } medianChannel[ yIndexContrib + x ] = (double)quick_select( buffer, boxSizeX*boxSizeY ) / 1000.0; delete [] buffer; } } // copy blurred image back into passed-in image memcpy( inChannel, medianChannel, sizeof(double) * inWidth * inHeight ); delete [] medianChannel; delete [] intChannel; } #endif between-6+dfsg1.orig/minorGems/graphics/filters/quickselect.h0000640000175000017500000000320611435543334023144 0ustar pabspabs/* * This Quickselect routine is based on the algorithm described in * "Numerical recipies in C", Second Edition, * Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5 */ #define ELEM_SWAP(a,b) { register int t=(a);(a)=(b);(b)=t; } int quick_select(int arr[], int n) { int low, high; int median; int middle, ll, hh; low = 0 ; high = n-1 ; median = (low + high) / 2; for (;;) { if (high <= low) /* One element only */ return arr[median] ; if (high == low + 1) { /* Two elements only */ if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; return arr[median] ; } /* Find median of low, middle and high items; swap into position low */ middle = (low + high) / 2; if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]) ; if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]) ; /* Swap low item (now in position middle) into position (low+1) */ ELEM_SWAP(arr[middle], arr[low+1]) ; /* Nibble from each end towards middle, swapping items when stuck */ ll = low + 1; hh = high; for (;;) { do ll++; while (arr[low] > arr[ll]) ; do hh--; while (arr[hh] > arr[low]) ; if (hh < ll) break; ELEM_SWAP(arr[ll], arr[hh]) ; } /* Swap middle item (in position low) back into correct position */ ELEM_SWAP(arr[low], arr[hh]) ; /* Re-set active partition */ if (hh <= median) low = ll; if (hh >= median) high = hh - 1; } } #undef ELEM_SWAP between-6+dfsg1.orig/minorGems/graphics/filters/BoxBlurFilter.h0000640000175000017500000001367511435543334023366 0ustar pabspabs/* * Modification History * * 2000-December-21 Jason Rohrer * Created. * * 2001-January-6 Jason Rohrer * Added a getRadius function for completeness. * * 2006-August-22 Jason Rohrer * Fixed major bug: sum for box must start at zero. * * 2006-September-7 Jason Rohrer * Optimized inner loop. * Optimized more, avoiding summing over entire box for each pixel. */ #ifndef BOX_BLUR_FILTER_INCLUDED #define BOX_BLUR_FILTER_INCLUDED #include "minorGems/graphics/ChannelFilter.h" /** * Blur convolution filter that uses a box for averaging. * * @author Jason Rohrer */ class BoxBlurFilter : public ChannelFilter { public: /** * Constructs a box filter. * * @param inRadius the radius of the box in pixels. */ BoxBlurFilter( int inRadius ); /** * Sets the box radius. * * @param inRadius the radius of the box in pixels. */ void setRadius( int inRadius ); /** * Gets the box radius. * * @return the radius of the box in pixels. */ int getRadius(); // implements the ChannelFilter interface void apply( double *inChannel, int inWidth, int inHeight ); private: int mRadius; }; inline BoxBlurFilter::BoxBlurFilter( int inRadius ) : mRadius( inRadius ) { } inline void BoxBlurFilter::setRadius( int inRadius ) { mRadius = inRadius; } inline int BoxBlurFilter::getRadius() { return mRadius; } inline void BoxBlurFilter::apply( double *inChannel, int inWidth, int inHeight ) { double *blurredChannel = new double[ inWidth * inHeight ]; // optimization: // The sum for a given pixel's box in row N is the sum for the same pixel // in row (N-1) minus one box-row of pixels and plus a box-row of pixels // We don't have to loop over the entire box for each pixel (instead, // we just add the new pixels and subtract the old as the box moves along) char lastRowSumsSet = false; double *lastRowSums = new double[ inWidth ]; // track the sums from single rows of boxes that we have already seen // Thus, when we need to "subtract a row" from our box sum, we can use // the precomputed version double *singleRowBoxSums = new double[ inWidth * inHeight ]; for( int y=0; y= inHeight ) { endBoxY = inHeight - 1; // box hanging over bottom edge // no rows to add to sum addARow = false; } int boxSizeY = endBoxY - startBoxY + 1; for( int x=0; x= inWidth ) { endBoxX = inWidth - 1; } int boxSizeX = endBoxX - startBoxX + 1; // sum all pixels in the box around this pixel double sum = 0; if( ! lastRowSumsSet ) { // do the "slow way" for the first row for( int boxY = startBoxY; boxY<=endBoxY; boxY++ ) { int yBoxIndexContrib = boxY * inWidth; double rowSum = 0; for( int boxX = startBoxX; boxX<=endBoxX; boxX++ ) { rowSum += inChannel[ yBoxIndexContrib + boxX ]; } sum += rowSum; // store row sum for future use singleRowBoxSums[ yBoxIndexContrib + x ] = rowSum; } } else { // we have sum for this pixel from the previous row // use it to avoid looping over entire box again sum = lastRowSums[ x ]; if( addARow ) { // add pixels from row at endBoxY int yBoxIndexContrib = endBoxY * inWidth; double rowSum = 0; for( int boxX = startBoxX; boxX<=endBoxX; boxX++ ) { rowSum += inChannel[ yBoxIndexContrib + boxX ]; } sum += rowSum; // store it for later when we will need to subtract it singleRowBoxSums[ yBoxIndexContrib + x ] = rowSum; } if( subtractARow ) { // subtract pixels from startBoxY of previous row's box int yBoxIndexContrib = (startBoxY - 1) * inWidth; // use pre-computed sum for the row we're subtracting sum -= singleRowBoxSums[ yBoxIndexContrib + x ]; } } // divide by number of pixels to complete the average blurredChannel[ pixelIndex ] = sum / (boxSizeX * boxSizeY); // save to use when computing box sum for next row lastRowSums[ x ] = sum; } // we now have valid last row sums that we can use for // all the rest of the rows lastRowSumsSet = true; } // copy blurred image back into passed-in image memcpy( inChannel, blurredChannel, sizeof(double) * inWidth * inHeight ); delete [] blurredChannel; delete [] lastRowSums; delete [] singleRowBoxSums; } #endif between-6+dfsg1.orig/minorGems/graphics/filters/ThresholdFilter.h0000640000175000017500000000265111435543334023735 0ustar pabspabs/* * Modification History * * 2000-December-21 Jason Rohrer * Created. */ #ifndef THRESHOLD_FILTER_INCLUDED #define THRESHOLD_FILTER_INCLUDED #include "minorGems/graphics/ChannelFilter.h" /** * Threshold filter. * * @author Jason Rohrer */ class ThresholdFilter : public ChannelFilter { public: /** * Constructs a threshold filter. * * @param inThreshold threshold value. Channel values * above or equal to inThreshold are set to 1, while * all other values are set to 0. */ ThresholdFilter( double inThreshold ); /** * Sets the threshold. * * @param inThreshold threshold value. Channel values * above or equal to inThreshold are set to 1, while * all other values are set to 0. */ void setThreshold( double inThreshold ); // implements the ChannelFilter interface void apply( double *inChannel, int inWidth, int inHeight ); private: double mThreshold; }; inline ThresholdFilter::ThresholdFilter( double inThreshold ) : mThreshold( inThreshold ) { } inline void ThresholdFilter::setThreshold( double inThreshold ) { mThreshold = inThreshold; } inline void ThresholdFilter::apply( double *inChannel, int inWidth, int inHeight ) { int numPixels = inWidth * inHeight; for( int i=0; i= mThreshold ) { inChannel[i] = 1.0; } else { inChannel[i] = 0.0; } } } #endif between-6+dfsg1.orig/minorGems/graphics/filters/SeamlessFilter.h0000640000175000017500000000740511435543334023557 0ustar pabspabs/* * Modification History * * 2001-January-19 Jason Rohrer * Created. * * 2006-September-25 Jason Rohrer * Added control over blending curve. * Reorderd loop for efficiency. */ #ifndef SEAMLESS_FILTER_INCLUDED #define SEAMLESS_FILTER_INCLUDED #include "minorGems/graphics/ChannelFilter.h" #include /** * Filter that turns any image into a seamless tile. * * @author Jason Rohrer */ class SeamlessFilter : public ChannelFilter { public: /** * Constructs a filter. * * @param inBlendCurveExponent the exponent of the blending curve * as we near the edge of the image. Defaults to 1 for a linear * blending curve. Setting to 2 would result in a parabolic * curve which would push the blended area closer to the edge * and leave more high-contrast, unblended image data near * the middle. */ SeamlessFilter( double inBlendCurveExponent = 1 ); // implements the ChannelFilter interface virtual void apply( double *inChannel, int inWidth, int inHeight ); private: double mBlendingCurveExponent; }; inline SeamlessFilter::SeamlessFilter( double inBlendCurveExponent ) : mBlendingCurveExponent( inBlendCurveExponent ) { } inline void SeamlessFilter::apply( double *inChannel, int inWidth, int inHeight ) { int numPixels = inWidth * inHeight; int halfHigh = inHeight/2; int halfWide = inWidth/2; // mix the texture with itself. // as we move closer and closer to the texture edge, we should // start mixing in more and more of the center values double *channelCopy = new double[ numPixels ]; // first, create an image with no seams if tiled horizontally // (getting rid of vertical seams) for( int x=0; x #include "IconMap.h" class GraphicBuffer { public: GraphicBuffer( unsigned long *buff, int buffW, int buffH ); ~GraphicBuffer(); // draw a solid image into the buffer void drawImage( unsigned long *image, int *imageYOffset, int xPos, int yPos, int wide, int high ); // draw a transparent image into the buffer void drawImageAlpha( unsigned long *image, int *imageYOffset, int xPos, int yPos, int wide, int high ); // replace a rectangle in the buffer with bgColor void eraseImage( int xPos, int yPos, int wide, int high, Color &bgColor ); // draw a solid IconMap into the buffer void drawIconMap( IconMap *icon, int xPos, int yPos ); // draw a transparent image into the buffer void drawIconMapAlpha( IconMap *icon, int xPos, int yPos ); // replace a rectangle (over icon) in the buffer with bgColor void eraseIconMap( IconMap *icon, int xPos, int yPos, Color &bgColor ); // set buffer to a new buffer of the same size void setBuffer( unsigned long *buff ); // get the pixel buffer unsigned long *getBuffer(); int getWidth(); int getHeight(); // fill buffer with a color void fill( Color &fillC ); // take a screen shot, save to disc void screenShot( FILE *f ); private: unsigned long *buffer; int bufferHigh; int bufferWide; int *buffYOffset; float invChannelMax; Color utilColor; // color for using composite functions }; inline GraphicBuffer::GraphicBuffer( unsigned long *buff, int buffW, int buffH) : utilColor(0,0,0,0) { invChannelMax = 1 / 255.0; bufferHigh = buffH; bufferWide = buffW; buffer = buff; // precalc'ed y contributions to linear indexing of buffer buffYOffset = new int[bufferHigh]; for( int y=0; y bufferHigh ) { maxY = bufferHigh; } int minX = xPos; if( minX < 0 ) { minX = 0; } int maxX = xPos + wide; if( maxX > bufferWide ) { maxX = bufferWide; } for( int y=minY; y bufferHigh ) { maxY = bufferHigh; } int minX = xPos; if( minX < 0 ) { minX = 0; } int maxX = xPos + wide; if( maxX > bufferWide ) { maxX = bufferWide; } unsigned long composite = bgColor.composite; for( int y=minY; y bufferHigh ) { maxY = bufferHigh; } int minX = xPos; if( minX < 0 ) { minX = 0; } int maxX = xPos + wide; if( maxX > bufferWide ) { maxX = bufferWide; } for( int y=minY; y> 24) * invChannelMax; float oneMinusAlpha = 1-alpha; unsigned long buffARGB = buffer[ buffYContrib + x ]; argb = utilColor.getWeightedComposite( argb, alpha ); buffARGB = utilColor.getWeightedComposite( buffARGB, oneMinusAlpha ); unsigned long sum = utilColor.sumComposite( argb, buffARGB ); buffer[ buffYContrib + x ] = sum; } } } inline void GraphicBuffer::drawIconMap( IconMap *icon, int xPos, int yPos ) { drawImage( icon->imageMap, icon->yOffset, xPos, yPos, icon->wide, icon->high ); } inline void GraphicBuffer::drawIconMapAlpha( IconMap *icon, int xPos, int yPos ) { drawImageAlpha( icon->imageMap, icon->yOffset, xPos, yPos, icon->wide, icon->high ); } inline void GraphicBuffer::eraseIconMap( IconMap *icon, int xPos, int yPos, Color &bgColor ) { eraseImage( xPos, yPos, icon->wide, icon->high, bgColor ); } inline void GraphicBuffer::fill( Color &fillC ) { unsigned long composite = fillC.composite; for( int y=0; y #include #include "Image.h" /** * An RGBA extension of Image. * * @author Jason Rohrer */ class RGBAImage : public Image { public: /** * Constructs an RGBA image. All channels are initialized to 0. * * @param inWidth width of image in pixels. * @param inHeight height of image in pixels. */ RGBAImage( int inWidth, int inHeight ); /** * Constructs an RGBAImage by copying a given image. * The image data is truncated or expaned (with black color channels * and white alpha) to fit the 4 channel RGBA model, * and any selection in inImage is ignored. * * @param inImage the image to copy. Copied internally, so must be * destroyed by the caller. */ RGBAImage( Image *inImage ); /** * Gets the pixel data from this image as a byte array. * * @return a byte array containing pixel data for this image. * Stored in row-major order, with each pixel represented * by 4 bytes in the order RGBA. * Must be destroyed by caller. */ virtual unsigned char *getRGBABytes(); // get RGBA a bytes from an image without converting it to an RGBA // image first (faster---found with profiler) // // MUST be a 3- or 4-channel image static unsigned char *getRGBABytes( Image *inImage ); // overrides the Image::filter function virtual void filter( ChannelFilter *inFilter ); virtual void filter( ChannelFilter *inFilter, int inChannel ); // overrides the Image::copy function // since the function is non-virtual in the parent class, // the pointer type should determine which function gets called. RGBAImage *copy(); }; inline RGBAImage::RGBAImage( int inWidth, int inHeight ) : Image( inWidth, inHeight, 4 ) { } inline RGBAImage::RGBAImage( Image *inImage ) // Only init our image's channels to black of inImage doesn't have enough // channels. // This saves time if inImage has 4 or more channels. // Optimization found with profiler. : Image( inImage->getWidth(), inImage->getHeight(), 4, ( inImage->getNumChannels() < 4 ) ) { int minNumChannels = 4; if( inImage->getNumChannels() < minNumChannels ) { minNumChannels = inImage->getNumChannels(); } // if inImage does not have at least 4 channels, // leave our additional channels black // if inImage has extra channels, skip them // copy channels from inImage for( int c=0; cgetChannel( c ); memcpy( mChannels[c], inChannel, mNumPixels * sizeof( double ) ); } if( minNumChannels < 4 ) { // no alpha channel in inImage // set a white one double *alpha = mChannels[3]; for( int i=0; igetWidth() * inImage->getHeight(); int numChannels = inImage->getNumChannels(); int numBytes = numPixels * 4; unsigned char *bytes = new unsigned char[ numBytes ]; double *channelZero = inImage->getChannel( 0 ); double *channelOne = inImage->getChannel( 1 ); double *channelTwo = inImage->getChannel( 2 ); // double-coded branch here to make it faster // (avoid a switch inside the loop if( numChannels > 3 ) { double *channelThree = inImage->getChannel( 3 ); register int i = 0; for( int p=0; ppaste( this ); return copiedImage; } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/0000750000175000017500000000000011503620617020165 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/graphics/openGL/NoLightingGL.h0000640000175000017500000000121011435543334022622 0ustar pabspabs/* * Modification History * * 2000-December-20 Jason Rohrer * Created. */ #ifndef NO_LIGHTING_GL_INCLUDED #define NO_LIGHTING_GL_INCLUDED #include "LightingGL.h" /** * LightingGL implementation that uses a constant white light everywhere. * * @author Jason Rohrer */ class NoLightingGL : public LightingGL{ public: // implements LightingGL interface void getLighting( Vector3D *inPoint, Vector3D *inNormal, Color *outColor ); }; inline void NoLightingGL::getLighting( Vector3D *inPoint, Vector3D *inNormal, Color *outColor ) { outColor->r = 1.0; outColor->g = 1.0; outColor->b = 1.0; } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/LightingGL.h0000640000175000017500000000146411435543334022340 0ustar pabspabs/* * Modification History * * 2000-December-20 Jason Rohrer * Created. */ #ifndef LIGHTING_GL_INCLUDED #define LIGHTING_GL_INCLUDED #include "minorGems/math/geometry/Vector3D.h" #include "minorGems/graphics/Color.h" /** * Interface for lighting in an OpenGL scene. * * @author Jason Rohrer */ class LightingGL { public: /** * Gets the lighting color for a particular point on a surface * with a particular orientation. * * @param inPoint the surface point. * @param inNormal direction vector for normal at surface point. * Must be normalized. * @param outColor preallocated Color where the lighting color * of this surface point will be returned. */ virtual void getLighting( Vector3D *inPoint, Vector3D *inNormal, Color *outColor ) = 0; }; #endif between-6+dfsg1.orig/minorGems/graphics/openGL/PrimitiveGL.h0000640000175000017500000003752711435543334022554 0ustar pabspabs/* * Modification History * * 2000-December-20 Jason Rohrer * Created. * * 2001-January-9 Jason Rohrer * Changed to contain a 3d/Primitive3D. Containment was used instead of * subclassing so that GL-independent primitive subclasses could all be * used with the same PrimitiveGL. * * 2001-January-16 Jason Rohrer * Changed the draw() function to take a Transform3D. * * 2001-January-19 Jason Rohrer * Changed to use the altered TextureGL class, which now supports * multi-texturing. * * 2001-January-30 Jason Rohrer * Changed to check for GL version 1.2 before using 1.2 features. * Implemented first generation of a non-ARB draw function. * Now we assume multi-texture is defined (because of the availability * of glext), but we check that it is supported at runtime. * * 2001-January-31 Jason Rohrer * Changed glMultiTexCoord2dARB to glMultiTexCoord2fARB to support * the non-1.2 version of multitexture. * Fixed a return error affecting the windows compile. * Fixed an ambiguous variable declaration. * * 2001-February-1 Jason Rohrer * Worked on the non-ARB multitexturing. * * 2001-February-2 Jason Rohrer * Decided to skip non-ARB multitexturing for now and just * use the first texture layer when built-in multitexturing isn't available. * * 2001-March-14 Jason Rohrer * Added support for paramatization and temporal animations. * * 2001-March-17 Jason Rohrer * Fixed a bug in some of the wrapper functions. * * 2001-September-15 Jason Rohrer * Fixed a memory leak in texture creation. */ #ifndef PRIMITIVE_GL_INCLUDED #define PRIMITIVE_GL_INCLUDED #include #include #include "TextureGL.h" #include "LightingGL.h" #include "minorGems/math/geometry/Transform3D.h" #include "minorGems/graphics/RGBAImage.h" #include "minorGems/graphics/3d/Primitive3D.h" #include "minorGems/graphics/openGL/NoLightingGL.h" // try and include extensions if multitexture isn't // built-in to gl.h #ifndef GL_ARB_multitexture #include #endif /** * OpenGL primitive object. * * Comprised of a triangle mesh, texture map, and anchor points. * * @author Jason Rohrer */ class PrimitiveGL { public: /** * Constructs a PrimitiveGL. * * No parameters are copied, so they should not be destroyed * or re-accessed by caller. All are destroyed when the * primitive is destroyed. * * @param inPrimitive the primitive to base this GL version on. */ PrimitiveGL( Primitive3D *inPrimitive ); ~PrimitiveGL(); /** * Draws the primitive (assumes an active openGL screen). * * @param inTransform the transform to perform on the primitive * before drawing it. * @param inLighting the lighting to use when drawing the primitive. */ void draw( Transform3D *inTransform, LightingGL *inLighting ); /** * Gets the number of parameters associated with this primitive. * * @return the number of parameters. */ virtual int getNumParameters(); /** * Gets the number of animations associated with this primitive. * * @return the number of animations. */ virtual int getNumAnimations(); /** * Sets a parameter for this primative. * * @param inParameterIndex the index of the parameter to set. * If an index for a non-existing parameter is specified, * this call has no effect. * @param inValue the value to set the parameter to, in [-1, 1]. * The default value for all parameters is 0. */ virtual void setParameter( int inParameterIndex, double inValue ); /** * Gets a parameter for this primative. * * @param inParameterIndex the index of the parameter to get. * If an index for a non-existing parameter is specified, * 0 is returned. * * @return the value of the parameter, in [-1, 1]. * The default value for all parameters is 0. */ virtual double getParameter( int inParameterIndex ); /** * Steps this primitive forward in time. * * @param inStepSize the size of the timestep to take. */ virtual void step( double inStepSize ); /** * Starts a temporal animation of this primitive. * The animation progresses as step() is called repeatedly. * If called for a non-existent animation or for one that is * already running, this function has no effect. */ virtual void startAnimation( int inAnimationIndex ); /** * Stops a temporal animation of this primitive. If called * for a non-existent animation or for one that is not currently * running, this function has no effect. */ virtual void stopAnimation( int inAnimationIndex ); protected: Primitive3D *mPrimitive; TextureGL *mTextureGL; // Equivalent to the public draw(), but does manual multi-texturing // by multi-pass rendering. Does not depend on ARB calls. void drawNoMultitexture( Transform3D *inTransform, LightingGL *inLighting ); }; inline PrimitiveGL::PrimitiveGL( Primitive3D *inPrimitive ) : mPrimitive( inPrimitive ) { int numTextures = mPrimitive->mNumTextures; mTextureGL = new TextureGL( numTextures ); for( int i=0; imTexture[i]->getRGBABytes(); mTextureGL->setTextureData( i, rgba, mPrimitive->mTexture[i]->getWidth(), mPrimitive->mTexture[i]->getHeight() ); delete [] rgba; } } inline PrimitiveGL::~PrimitiveGL() { delete mPrimitive; delete mTextureGL; } // this is the ARB version of draw inline void PrimitiveGL::draw( Transform3D *inTransform, LightingGL *inLighting ) { // check for multi-texture availability before proceeding if( !TextureGL::isMultiTexturingSupported() ) { drawNoMultitexture( inTransform, inLighting ); return; } // first, copy the vertices and translate/rotate/scale them Vector3D **worldVertices = new Vector3D*[ mPrimitive->mNumVertices ]; Vector3D **worldNormals = new Vector3D*[ mPrimitive->mNumVertices ]; for( int i=0; imNumVertices; i++ ) { // copy worldVertices[i] = new Vector3D( mPrimitive->mVertices[i] ); worldNormals[i] = new Vector3D( mPrimitive->mNormals[i] ); // translate/rotate/scale inTransform->apply( worldVertices[i] ); // only rotate normals inTransform->applyNoTranslation( worldNormals[i] ); // normalize to get rid of any scaling worldNormals[i]->normalize(); } // now draw vertices as triangle strips mTextureGL->enable(); int numTextureLayers = mTextureGL->getNumLayers(); int t; if( mPrimitive->isTransparent() ) { glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); } else { glDisable( GL_BLEND ); } if( mPrimitive->isBackVisible() ) { glDisable( GL_CULL_FACE ); } else { glEnable( GL_CULL_FACE ); glCullFace( GL_BACK ); glFrontFace( GL_CCW ); } Color *lightColor = new Color( 0, 0, 0, 1.0 ); // for each strip of triangles for( int y=0; ymHigh-1; y++ ) { // note that we skip the last row of verts, since they are the bottom // of the last strip. int thisRow = y * mPrimitive->mWide; int nextRow = ( y + 1 ) * mPrimitive->mWide; glBegin( GL_TRIANGLE_STRIP ); // draw first triangle // first vert in next row int index = nextRow + 0; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); // pass in each layer's anchor points for( t=0; tmAnchorX[t][ index ], mPrimitive->mAnchorY[t][ index ] ); } glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); index = thisRow + 0; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); // pass in each layer's anchor points for( t=0; tmAnchorX[t][ index ], mPrimitive->mAnchorY[t][ index ] ); } glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); index = nextRow + 1; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); // pass in each layer's anchor points for( t=0; tmAnchorX[t][ index ], mPrimitive->mAnchorY[t][ index ] ); } glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); // draw next vertex to complete first "rectangle" index = thisRow + 1; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); // pass in each layer's anchor points for( t=0; tmAnchorX[t][ index ], mPrimitive->mAnchorY[t][ index ] ); } glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); // then add rest of vertices as part of strip for( int x=2; xmWide; x++ ) { // every additional pair of vertices completes // another "rectangle" index = nextRow + x; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); // pass in each layer's anchor points for( t=0; tmAnchorX[t][ index ], mPrimitive->mAnchorY[t][ index ] ); } glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); index = thisRow + x; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); // pass in each layer's anchor points for( t=0; tmAnchorX[t][ index ], mPrimitive->mAnchorY[t][ index ] ); } glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); } glEnd(); } mTextureGL->disable(); // cleanup for( int i=0; imNumVertices; i++ ) { delete worldVertices[i]; delete worldNormals[i]; } delete [] worldVertices; delete [] worldNormals; delete lightColor; } // this is the non-ARB version of draw inline void PrimitiveGL::drawNoMultitexture( Transform3D *inTransform, LightingGL *inLighting ) { // first, copy the vertices and translate/rotate/scale them Vector3D **worldVertices = new Vector3D*[ mPrimitive->mNumVertices ]; Vector3D **worldNormals = new Vector3D*[ mPrimitive->mNumVertices ]; for( int i=0; imNumVertices; i++ ) { // copy worldVertices[i] = new Vector3D( mPrimitive->mVertices[i] ); worldNormals[i] = new Vector3D( mPrimitive->mNormals[i] ); // translate/rotate/scale inTransform->apply( worldVertices[i] ); // only rotate normals inTransform->applyNoTranslation( worldNormals[i] ); // normalize to get rid of any scaling worldNormals[i]->normalize(); } Color *lightColor = new Color( 0, 0, 0, 1.0 ); // now draw vertices as triangle strips mTextureGL->enable(); if( mPrimitive->isTransparent() ) { glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); } else { glDisable( GL_BLEND ); } if( mPrimitive->isBackVisible() ) { glDisable( GL_CULL_FACE ); } else { glEnable( GL_CULL_FACE ); glCullFace( GL_BACK ); glFrontFace( GL_CCW ); } // for each strip of triangles for( int y=0; ymHigh-1; y++ ) { // note that we skip the last row of verts, since they are the bottom // of the last strip. int thisRow = y * mPrimitive->mWide; int nextRow = ( y + 1 ) * mPrimitive->mWide; glBegin( GL_TRIANGLE_STRIP ); // draw first triangle // first vert in next row int index = nextRow + 0; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); glTexCoord2d( mPrimitive->mAnchorX[0][ index ], mPrimitive->mAnchorY[0][ index ] ); glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); index = thisRow + 0; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); glTexCoord2d( mPrimitive->mAnchorX[0][ index ], mPrimitive->mAnchorY[0][ index ] ); glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); index = nextRow + 1; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); glTexCoord2d( mPrimitive->mAnchorX[0][ index ], mPrimitive->mAnchorY[0][ index ] ); glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); // draw next vertex to complete first "rectangle" index = thisRow + 1; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); glTexCoord2d( mPrimitive->mAnchorX[0][ index ], mPrimitive->mAnchorY[0][ index ] ); glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); // then add rest of vertices as part of strip for( int x=2; xmWide; x++ ) { // every additional pair of vertices completes // another "rectangle" index = nextRow + x; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); glTexCoord2d( mPrimitive->mAnchorX[0][ index ], mPrimitive->mAnchorY[0][ index ] ); glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); index = thisRow + x; inLighting->getLighting( worldVertices[index], worldNormals[index], lightColor ); glColor4f( lightColor->r, lightColor->g, lightColor->b, 1.0 ); glTexCoord2d( mPrimitive->mAnchorX[0][ index ], mPrimitive->mAnchorY[0][ index ] ); glVertex3d( worldVertices[index]->mX, worldVertices[index]->mY, worldVertices[index]->mZ ); } glEnd(); } mTextureGL->disable(); // cleanup for( int i=0; imNumVertices; i++ ) { delete worldVertices[i]; delete worldNormals[i]; } delete [] worldVertices; delete [] worldNormals; delete lightColor; } // these all just wrap the functions of the underlying Primitive3D inline int PrimitiveGL::getNumParameters() { return mPrimitive->getNumParameters(); } inline int PrimitiveGL::getNumAnimations() { return mPrimitive->getNumAnimations(); } inline void PrimitiveGL::setParameter( int inParameterIndex, double inValue ) { mPrimitive->setParameter( inParameterIndex, inValue ); } inline double PrimitiveGL::getParameter( int inParameterIndex ) { return mPrimitive->getParameter( inParameterIndex ); } inline void PrimitiveGL::step( double inStepSize ) { mPrimitive->step( inStepSize ); } inline void PrimitiveGL::startAnimation( int inAnimationIndex ) { mPrimitive->startAnimation( inAnimationIndex ); } inline void PrimitiveGL::stopAnimation( int inAnimationIndex ) { mPrimitive->stopAnimation( inAnimationIndex ); } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/AmbientLightingGL.h0000640000175000017500000000243111435543334023633 0ustar pabspabs/* * Modification History * * 2001-January-17 Jason Rohrer * Created. */ #ifndef AMBIENT_LIGHTING_GL_INCLUDED #define AMBIENT_LIGHTING_GL_INCLUDED #include "LightingGL.h" /** * LightingGL implementation that uses constant, specifiable * light values everywhere. Most useful when combined with * directional or point lightings using MultiLighting. * * Setting color to full white makes this lighting equivalent * to a NoLightingGL. * * @author Jason Rohrer */ class AmbientLightingGL : public LightingGL{ public: /** * Constructs an AmbientLighting. * * @param inColor color and intensity of lighting. * Is not copied, so cannot be accessed again by caller. */ AmbientLightingGL( Color *inColor ); ~AmbientLightingGL(); // implements LightingGL interface void getLighting( Vector3D *inPoint, Vector3D *inNormal, Color *outColor ); private: Color *mColor; }; inline AmbientLightingGL::AmbientLightingGL( Color *inColor ) : mColor( inColor ) { } inline AmbientLightingGL::~AmbientLightingGL() { delete mColor; } inline void AmbientLightingGL::getLighting( Vector3D *inPoint, Vector3D *inNormal, Color *outColor ) { outColor->r = mColor->r; outColor->g = mColor->g; outColor->b = mColor->b; } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/SingleTextureGL.cpp0000640000175000017500000001533211435543334023727 0ustar pabspabs/* * Modification History * * 2005-February-21 Jason Rohrer * Created. * * 2005-August-24 Jason Rohrer * Added control over texture wrapping. * * 2009-September-9 Jason Rohrer * Added direct RGBA construction. * * 2009-November-5 Jason Rohrer * Added texture data replacement. * * 2010-April-20 Jason Rohrer * Reload all SingleTextures after GL context change. */ #include "SingleTextureGL.h" SimpleVector SingleTextureGL::sAllLoadedTextures; void SingleTextureGL::contextChanged() { // tell all textures to reload int numTextures = sAllLoadedTextures.size(); printf( "Reloading %d textures due to OpenGL context change\n", numTextures ); for( int i=0; ireloadFromBackup(); } } void SingleTextureGL::reloadFromBackup() { if( mRGBABackup != NULL ) { glGenTextures( 1, &mTextureID ); int error = glGetError(); if( error != GL_NO_ERROR ) { // error printf( "Error generating new texture ID, error = %d, \"%s\"\n", error, glGetString( error ) ); } setTextureData( mRGBABackup, mWidthBackup, mHeightBackup ); } } SingleTextureGL::SingleTextureGL( Image *inImage, char inRepeat ) : mRepeat( inRepeat ), mRGBABackup( NULL ) { glGenTextures( 1, &mTextureID ); int error = glGetError(); if( error != GL_NO_ERROR ) { // error printf( "Error generating new texture ID, error = %d, \"%s\"\n", error, glGetString( error ) ); } setTextureData( inImage ); sAllLoadedTextures.push_back( this ); } SingleTextureGL::SingleTextureGL( unsigned char *inRGBA, unsigned int inWidth, unsigned int inHeight, char inRepeat ) : mRepeat( inRepeat ), mRGBABackup( NULL ) { glGenTextures( 1, &mTextureID ); int error = glGetError(); if( error != GL_NO_ERROR ) { // error printf( "Error generating new texture ID, error = %d, \"%s\"\n", error, glGetString( error ) ); } setTextureData( inRGBA, inWidth, inHeight ); sAllLoadedTextures.push_back( this ); } SingleTextureGL::~SingleTextureGL() { sAllLoadedTextures.deleteElementEqualTo( this ); glDeleteTextures( 1, &mTextureID ); if( mRGBABackup != NULL ) { delete [] mRGBABackup; mRGBABackup = NULL; } } void SingleTextureGL::setTextureData( Image *inImage ) { // first, convert our image to an RGBAImage RGBAImage *rgbaImage = new RGBAImage( inImage ); if( inImage->getNumChannels() < 4 ) { // we should fill in 1.0 for the alpha channel // since the input image doesn't have an alpha channel double *channel = rgbaImage->getChannel( 3 ); int numPixels = inImage->getWidth() * inImage->getHeight(); for( int i=0; igetRGBABytes(); setTextureData( textureData, rgbaImage->getWidth(), rgbaImage->getHeight() ); delete rgbaImage; delete [] textureData; } void SingleTextureGL::setTextureData( unsigned char *inRGBA, unsigned int inWidth, unsigned int inHeight ) { if( inRGBA != mRGBABackup ) { // clear old backup if( mRGBABackup != NULL ) { delete [] mRGBABackup; mRGBABackup = NULL; } mRGBABackup = new unsigned char[ inWidth * inHeight * 4 ]; memcpy( mRGBABackup, inRGBA, inWidth * inHeight * 4 ); mWidthBackup = inWidth; mHeightBackup = inHeight; } int error; GLenum texFormat = GL_RGBA; glBindTexture( GL_TEXTURE_2D, mTextureID ); error = glGetError(); if( error != GL_NO_ERROR ) { // error printf( "Error binding to texture id %d, error = %d\n", (int)mTextureID, error ); } glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); if( mRepeat ) { glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); } else { glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); } glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); glTexImage2D( GL_TEXTURE_2D, 0, texFormat, inWidth, inHeight, 0, texFormat, GL_UNSIGNED_BYTE, inRGBA ); error = glGetError(); if( error != GL_NO_ERROR ) { // error printf( "Error setting texture data for id %d, error = %d, \"%s\"\n", (int)mTextureID, error, glGetString( error ) ); printf( "Perhaps texture image width or height is not a power of 2\n" "Width = %u, Height = %u\n", inWidth, inHeight ); } } void SingleTextureGL::replaceTextureData( unsigned char *inRGBA, unsigned int inWidth, unsigned int inHeight ) { if( inRGBA != mRGBABackup ) { // clear old backup if( mRGBABackup != NULL ) { delete [] mRGBABackup; mRGBABackup = NULL; } mRGBABackup = new unsigned char[ inWidth * inHeight * 4]; memcpy( mRGBABackup, inRGBA, inWidth * inHeight * 4 ); mWidthBackup = inWidth; mHeightBackup = inHeight; } int error; GLenum texFormat = GL_RGBA; glBindTexture( GL_TEXTURE_2D, mTextureID ); error = glGetError(); if( error != GL_NO_ERROR ) { // error printf( "Error binding to texture id %d, error = %d\n", (int)mTextureID, error ); } glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, // offset inWidth, inHeight, texFormat, GL_UNSIGNED_BYTE, inRGBA ); error = glGetError(); if( error != GL_NO_ERROR ) { // error printf( "Error replacing texture data for id %d, error = %d, \"%s\"\n", (int)mTextureID, error, glGetString( error ) ); printf( "Perhaps texture image width or height is not a power of 2\n" "Width = %u, Height = %u\n", inWidth, inHeight ); } } between-6+dfsg1.orig/minorGems/graphics/openGL/MouseHandlerGL.h0000640000175000017500000000265711435543334023166 0ustar pabspabs/* * Modification History * * 2000-December-19 Jason Rohrer * Created. * * 2010-April-6 Jason Rohrer * Blocked event passing to handlers that were added by event. */ #ifndef MOUSE_HANDLER_GL_INCLUDED #define MOUSE_HANDLER_GL_INCLUDED /** * Interface for an object that can field OpenGL mouse events. * * @author Jason Rohrer */ class MouseHandlerGL { public: virtual ~MouseHandlerGL() { } /** * Callback function for when mouse moves. * * @param inX x position of mouse. * @param inY y position of mouse. */ virtual void mouseMoved( int inX, int inY ) = 0; /** * Callback function for when mouse moves with button depressed. * * @param inX x position of mouse. * @param inY y position of mouse. */ virtual void mouseDragged( int inX, int inY ) = 0; /** * Callback function for when the mouse button is depressed. * * @param inX x position of mouse. * @param inY y position of mouse. */ virtual void mousePressed( int inX, int inY ) = 0; /** * Callback function for when the mouse button is released. * * @param inX x position of mouse. * @param inY y position of mouse. */ virtual void mouseReleased( int inX, int inY ) = 0; char mHandlerFlagged; protected: MouseHandlerGL() : mHandlerFlagged( false ) { } }; #endif between-6+dfsg1.orig/minorGems/graphics/openGL/ScreenGL.h0000640000175000017500000003223311435543334022010 0ustar pabspabs/* * Modification History * * 2000-December-19 Jason Rohrer * Created. * * 2001-January-15 Jason Rohrer * Added compile instructions for Linux to the comments. * * 2001-February-4 Jason Rohrer * Added a function for getting the view angle. * Added support for keyboard up functions. * Added support for redraw listeners. * Added a missing destructor. * * 2001-August-29 Jason Rohrer * Added support for adding and removing mouse, keyboard, and scene handlers. * * 2001-August-30 Jason Rohrer * Fixed some comments. * * 2001-September-15 Jason Rohrer * Added functions for accessing the screen size. * * 2001-October-13 Jason Rohrer * Added a function for applying the view matrix transformation. * * 2001-October-29 Jason Rohrer * Added a private function that checks for focused keyboard handlers. * * 2004-June-11 Jason Rohrer * Added functions for getting/setting view position. * * 2004-June-14 Jason Rohrer * Added comment about need for glutInit call. * * 2006-December-21 Jason Rohrer * Added functions for changing window size and switching to full screen. * * 2008-September-12 Jason Rohrer * Changed to use glutEnterGameMode for full screen at startup. * Added a 2D graphics mode. * * 2008-September-29 Jason Rohrer * Enabled ignoreKeyRepeat. * * 2008-October-27 Jason Rohrer * Prepared for alternate implementations besides GLUT. * Switched to implementation-independent keycodes. * Added support for setting viewport size separate from screen size. * * 2010-April-20 Jason Rohrer * Alt-Enter to leave fullscreen mode. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ #ifndef SCREEN_GL_INCLUDED #define SCREEN_GL_INCLUDED #include "MouseHandlerGL.h" #include "KeyboardHandlerGL.h" #include "SceneHandlerGL.h" #include "RedrawListenerGL.h" #include "minorGems/math/geometry/Vector3D.h" #include "minorGems/math/geometry/Angle3D.h" #include "minorGems/util/SimpleVector.h" // prototypes void callbackResize( int inW, int inH ); void callbackKeyboard( unsigned char inKey, int inX, int inY ); void callbackKeyboardUp( unsigned char inKey, int inX, int inY ); void callbackSpecialKeyboard( int inKey, int inX, int inY ); void callbackSpecialKeyboardUp( int inKey, int inX, int inY ); void callbackMotion( int inX, int inY ); void callbackPassiveMotion( int inX, int inY ); void callbackMouse( int inButton, int inState, int inX, int inY ); void callbackDisplay(); void callbackIdle(); /** * Object that handles general initialization of an OpenGL screen. * * @author Jason Rohrer */ class ScreenGL { public: /** * Constructs a ScreenGL. * * GLUT implementation only: * Before calling this constructor, glutInit must be called with * the application's command-line arguments. For example, if * the application's main function looks like: * * int main( int inNumArgs, char **inArgs ) { ... } * * Then you must call glutInit( &inNumArgs, inArgs ) before * constructing a screen. * * SDL implementation: * Must call SDL_Init() with at least SDL_INIT_VIDEO * as a parameter. * * @param inWide width of screen. * @param inHigh height of screen. * @param inFullScreen set to true for full screen mode. * NOTE that full screen mode requires inWide and inHigh to match * an available screen resolution. * @param inWindowName name to be displayed on title bar of window. * @param inKeyHandler object that will receive keyboard events. * NULL specifies no handler (defaults to NULL). * Must be destroyed by caller. * @param inMouseHandler object that will receive mouse events. * NULL specifies no handler (defaults to NULL). * Must be destroyed by caller. * @param inSceneHandler object that will be called to draw * the scene during in response to redraw events. * NULL specifies no handler (defaults to NULL). * Must be destroyed by caller. */ ScreenGL( int inWide, int inHigh, char inFullScreen, const char *inWindowName, KeyboardHandlerGL *inKeyHandler = NULL, MouseHandlerGL *inMouseHandler = NULL, SceneHandlerGL *inSceneHandler = NULL ); /** * Destructor closes and releases the screen. */ ~ScreenGL(); /** * Starts the GLUT main loop. * * Note that this function call never returns. */ void start(); /** * Switches to 2D mode, where no view transforms are applied * * Must be called before start(); */ void switchTo2DMode(); /** * Moves the view position. * * @param inPositionChange directional vector describing motion. * Must be destroyed by caller. */ void moveView( Vector3D *inPositionChange ); /** * Rotates the view. * * @param inOrientationChange angle to rotate view by. * Must be destroyed by caller. */ void rotateView( Angle3D *inOrientationChange ); /** * Gets the angle of the current view direction. * * @return the angle of the current view direction. * Not a copy, so shouldn't be modified or destroyed by caller. */ Angle3D *getViewOrientation(); /** * Gets the current view position. * * @return the position of the current view. * Must be destroyed by caller. */ Vector3D *getViewPosition(); /** * Sets the current view position. * * @param inPosition the new position. * Must be destroyed by caller. */ void setViewPosition( Vector3D *inPosition ); /** * Gets the width of the screen. * * @return the width of the screen, in pixels. */ int getWidth(); /** * Gets the height of the screen. * * @return the height of the screen, in pixels. */ int getHeight(); /** * Switches into full screen mode. * * Use changeWindowSize to switch back out of full screen mode. */ void setFullScreen(); /** * Sets the size of the viewport image in the window. * * Defaults to window size. * * Must be called before screen is started. * * @param inWidth, inHeight the new dimensions, in pixels. */ void setImageSize( int inWidth, int inHeight ); /** * Gets the width of the viewport image. * * @return the width of the viewport, in pixels. */ int getImageWidth(); /** * Gets the height of the viewport image. * * @return the height of the viewport, in pixels. */ int getImageHeight(); /** * Change the window size. * * @param inWidth, inHeight the new dimensions, in pixels. */ void changeWindowSize( int inWidth, int inHeight ); /** * Adds a mouse handler. * * @param inHandler the handler to add Must * be destroyed by caller. * * Must not be called after calling start(). */ void addMouseHandler( MouseHandlerGL *inHandler ); /** * Removes a mouse handler. * * @param inHandler the handler to remove. Must * be destroyed by caller. * * Must not be called after calling start(). */ void removeMouseHandler( MouseHandlerGL *inHandler ); /** * Adds a keyboard handler. * * @param inHandler the handler to add Must * be destroyed by caller. * * Must not be called after calling start(). */ void addKeyboardHandler( KeyboardHandlerGL *inHandler ); /** * Removes a keyboard handler. * * @param inHandler the handler to remove. Must * be destroyed by caller. * * Must not be called after calling start(). */ void removeKeyboardHandler( KeyboardHandlerGL *inHandler ); /** * Adds a scene handler. * * @param inHandler the handler to add Must * be destroyed by caller. * * Must not be called after calling start(). */ void addSceneHandler( SceneHandlerGL *inHandler ); /** * Removes a scene handler. * * @param inHandler the handler to remove. Must * be destroyed by caller. * * Must not be called after calling start(). */ void removeSceneHandler( SceneHandlerGL *inHandler ); /** * Adds a redraw listener. * * @param inListener the listener to add. Must * be destroyed by caller. * * Must not be called after calling start(). */ void addRedrawListener( RedrawListenerGL *inListener ); /** * Removes a redraw listener. * * @param inListener the listener to remove. Must * be destroyed by caller. * * Must not be called after calling start(). */ void removeRedrawListener( RedrawListenerGL *inListener ); /** * Applies the current view matrix transformation * to the matrix at the top of the GL_PROJECTION stack. */ void applyViewTransform(); /** * Access the various handlers. */ //KeyboardHandlerGL *getKeyHandler(); //MouseHandlerGL *getMouseHandler(); //SceneHandlerGL *getSceneHandler(); private : void setupSurface(); // used by various implementations // callbacks (external C functions that can access private members) friend void callbackResize( int inW, int inH ); friend void callbackKeyboard( unsigned char inKey, int inX, int inY ); friend void callbackKeyboardUp( unsigned char inKey, int inX, int inY ); friend void callbackSpecialKeyboard( int inKey, int inX, int inY ); friend void callbackSpecialKeyboardUp( int inKey, int inX, int inY ); friend void callbackMotion( int inX, int inY ); friend void callbackPassiveMotion( int inX, int inY ); friend void callbackMouse( int inButton, int inState, int inX, int inY ); friend void callbackDisplay(); friend void callbackIdle(); // our private members int mWide; int mHigh; // for an viewport image that can be smaller than our screen char mImageSizeSet; int mImageWide; int mImageHigh; char mFullScreen; // only allow ALT-Enter to toggle fullscreen if it started there char mStartedFullScreen; char m2DMode; Vector3D *mViewPosition; // orientation of 0,0,0 means looking in the direction (0,0,1) // with an up direction of (0,1,0) Angle3D *mViewOrientation; // vectors of handlers and listeners SimpleVector *mMouseHandlerVector; SimpleVector *mKeyboardHandlerVector; SimpleVector *mSceneHandlerVector; SimpleVector *mRedrawListenerVector; /** * Gets whether at least one of our keyboard handlers is focused. * * @return true iff at least one keyboard handler is focused. */ char isKeyboardHandlerFocused(); }; inline void ScreenGL::moveView( Vector3D *inPositionChange ) { mViewPosition->add( inPositionChange ); } inline void ScreenGL::rotateView( Angle3D *inOrientationChange ) { mViewOrientation->add( inOrientationChange ); } inline Angle3D *ScreenGL::getViewOrientation() { return mViewOrientation; } inline Vector3D *ScreenGL::getViewPosition() { return new Vector3D( mViewPosition ); } inline void ScreenGL::setViewPosition( Vector3D *inPosition ) { delete mViewPosition; mViewPosition = new Vector3D( inPosition ); } inline int ScreenGL::getWidth() { return mWide; } inline int ScreenGL::getHeight() { return mHigh; } inline void ScreenGL::setImageSize( int inWidth, int inHeight ) { mImageSizeSet = true; mImageWide = inWidth; mImageHigh = inHeight; } inline int ScreenGL::getImageWidth() { return mImageWide; } inline int ScreenGL::getImageHeight() { return mImageHigh; } inline void ScreenGL::addRedrawListener( RedrawListenerGL *inListener ) { mRedrawListenerVector->push_back( inListener ); } inline void ScreenGL::removeRedrawListener( RedrawListenerGL *inListener ) { mRedrawListenerVector->deleteElementEqualTo( inListener ); } inline void ScreenGL::addMouseHandler( MouseHandlerGL *inListener ) { mMouseHandlerVector->push_back( inListener ); } inline void ScreenGL::removeMouseHandler( MouseHandlerGL *inListener ) { mMouseHandlerVector->deleteElementEqualTo( inListener ); } inline void ScreenGL::addKeyboardHandler( KeyboardHandlerGL *inListener ) { mKeyboardHandlerVector->push_back( inListener ); } inline void ScreenGL::removeKeyboardHandler( KeyboardHandlerGL *inListener ) { mKeyboardHandlerVector->deleteElementEqualTo( inListener ); } inline void ScreenGL::addSceneHandler( SceneHandlerGL *inListener ) { mSceneHandlerVector->push_back( inListener ); } inline void ScreenGL::removeSceneHandler( SceneHandlerGL *inListener ) { mSceneHandlerVector->deleteElementEqualTo( inListener ); } inline char ScreenGL::isKeyboardHandlerFocused() { for( int h=0; hsize(); h++ ) { KeyboardHandlerGL *handler = *( mKeyboardHandlerVector->getElement( h ) ); if( handler->isFocused() ) { return true; } } // else none were focused return false; } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/testNavigatorGL.cpp0000640000175000017500000000102711435543334023753 0ustar pabspabs/* * Modification History * * 2001-August-29 Jason Rohrer * Created. */ #include "TestSceneHandlerGL.h" #include "SceneNavigatorDisplayGL.h" #include "minorGems/util/random/StdRandomSource.h" // simple test function int main() { StdRandomSource *randSource = new StdRandomSource( 2 ); TestSceneHandlerGL *handler = new TestSceneHandlerGL(); char *name = "test window"; SceneNavigatorDisplayGL *screen = new SceneNavigatorDisplayGL( 200, 200, false, name, handler ); screen->start(); return 0; } between-6+dfsg1.orig/minorGems/graphics/openGL/SceneNavigatorDisplayGL.h0000640000175000017500000002046111435543334025027 0ustar pabspabs/* * Modification History * * 2001-August-29 Jason Rohrer * Created. * * 2001-August-30 Jason Rohrer * Fixed some comments. * * 2001-October-29 Jason Rohrer * Changed to move and rotate view at a fixed * time rate, regardless of framerate. * * 2003-June-14 Jason Rohrer * Fixed namespace for exit call. * Added M_PI backup definition. */ #ifndef SCENE_NAVIGATOR_DISPLAY_GL_INCLUDED #define SCENE_NAVIGATOR_DISPLAY_GL_INCLUDED #include "ScreenGL.h" #include "MouseHandlerGL.h" #include "KeyboardHandlerGL.h" #include "SceneHandlerGL.h" #include "RedrawListenerGL.h" #include "minorGems/system/Time.h" #include #include // make sure M_PI is defined #ifndef M_PI #define M_PI 3.14159265358979323846 #endif /** * Subclass of ScreenGL that handles general-purpose 3D scene navigation * rendered through OpenGL. * * Motion is unlimited, though forward-backward motion is confinded * to the x-z plane (the user can move up and down explicitly, however). * * To constrict motion, subclass SceneNavigatorDisplayGL and override * the moveView() function (a member of ScreenGL). * * Compile note: For Linux, add these library flags: * -lGL -lglut -lGLU -L/usr/X11R6/lib * Be sure to include ScreenGL.cpp in the file list passed to the compiler. * * @author Jason Rohrer */ class SceneNavigatorDisplayGL : public ScreenGL, public MouseHandlerGL, public KeyboardHandlerGL, public RedrawListenerGL { public: /** * Constructs a navigator. * * @param inWide the width of the screen in pixels. * @param inHigh the height of the screen in pixels. * @param inFullScreen true iff the display should * fill the screen. * @param inWindowName the name of the display window. * @param inSceenHandler the handler responsible for * drawing the scene. * Must be destroyed by caller. * @param inMoveUnitsPerSecond the number of world * units to move per second when the user makes a move. * Defaults to 1.0 units per second. * @param inRotateRadiansPerSecond the number of * radians to rotate per second when the user makes a rotation. * Defaults to 1.0 radians per second. */ SceneNavigatorDisplayGL( int inWide, int inHigh, char inFullScreen, char *inWindowName, SceneHandlerGL *inSceneHandler, double inMoveUnitsPerSecond = 1.0, double inRotateRadiansPerSecond = 1.0 ); ~SceneNavigatorDisplayGL(); // implements the MouseHandlerGL interface virtual void mouseMoved( int inX, int inY ); virtual void mouseDragged( int inX, int inY ); virtual void mousePressed( int inX, int inY ); virtual void mouseReleased( int inX, int inY ); // implements the KeyboardHandlerGL interface virtual void keyPressed( unsigned char inKey, int inX, int inY ); virtual void specialKeyPressed( int inKey, int inX, int inY ); virtual void keyReleased( unsigned char inKey, int inX, int inY ); virtual void specialKeyReleased( int inKey, int inX, int inY ); // implements the RedrawListener interface virtual void fireRedraw(); private : int mLastMouseX, mLastMouseY; // amount to move and rotate view during each redraw Vector3D *mMoveDirection; Angle3D *mRotationOffset; // keep y movement separate from view direction. double mYMovement; // true if a moving key is currently depressed char mMoving; // true if a rotation key is currently depressed char mRotating; unsigned long mTimeLastRedrawS; unsigned long mTimeLastRedrawMS; double mMoveUnitsPerSecond; double mRotateRadiansPerSecond; }; inline SceneNavigatorDisplayGL::SceneNavigatorDisplayGL( int inWide, int inHigh, char inFullScreen, char *inWindowName, SceneHandlerGL *inSceneHandler, double inMoveUnitsPerSecond, double inRotateRadiansPerSecond ) : ScreenGL( inWide, inHigh, inFullScreen, inWindowName, NULL, NULL, inSceneHandler ), mMoveDirection( new Vector3D( 0, 0, 0 ) ), mRotationOffset( new Angle3D( 0, 0, 0 ) ), mMoving( false ), mRotating( false ), mYMovement( 0 ), mMoveUnitsPerSecond( inMoveUnitsPerSecond ), mRotateRadiansPerSecond( inRotateRadiansPerSecond ) { // add ourself to the superclass' listener lists addMouseHandler( this ); addKeyboardHandler( this ); addRedrawListener( this ); Time::getCurrentTime( &mTimeLastRedrawS, &mTimeLastRedrawMS ); } inline void SceneNavigatorDisplayGL::mouseMoved( int inX, int inY ) { //printf( "mouse moved to (%d, %d)\n", inX, inY ); } inline void SceneNavigatorDisplayGL::mouseDragged( int inX, int inY ) { int delX = inX - mLastMouseX; int delY = inY - mLastMouseY; Angle3D *rotAngle = new Angle3D( delY / 50, delX/50, 0 ); //mScreen->rotateView( rotAngle ); delete rotAngle; mLastMouseX = inX; mLastMouseY = inY; } inline void SceneNavigatorDisplayGL::mousePressed( int inX, int inY ) { } inline void SceneNavigatorDisplayGL::mouseReleased( int inX, int inY ) { } inline void SceneNavigatorDisplayGL::keyPressed( unsigned char inKey, int inX, int inY ) { if( inKey == 'y' || inKey == 'Y' ) { // turn view downwards mRotationOffset->mX = M_PI/20; } else if( inKey == 'h' || inKey == 'H' ) { // turn view upwards mRotationOffset->mX = -M_PI/20; } if( inKey == 's' || inKey == 'S' ) { // turn to the left mRotationOffset->mY = M_PI/20; } else if( inKey == 'f' || inKey == 'F' ) { // turn to the right mRotationOffset->mY = -M_PI/20; } if( inKey == 'i' || inKey == 'I' ) { // move upwards mYMovement = 1; } else if( inKey == 'k' || inKey == 'K' ) { // move downwards mYMovement = -1; } if( inKey == 'j' || inKey == 'J' ) { // strafe to the left mMoveDirection->mX = 1; } else if( inKey == 'l' || inKey == 'L' ) { // strafe to the right mMoveDirection->mX = -1; } if( inKey == 'e' || inKey == 'E' ) { // move forward mMoveDirection->mZ = 1; } else if( inKey == 'd' || inKey == 'D' ) { // move backward mMoveDirection->mZ = -1; } else if( inKey == 'q' || inKey == 'Q' ) { // quit ::exit( 0 ); } } inline void SceneNavigatorDisplayGL::keyReleased( unsigned char inKey, int inX, int inY ) { if( inKey == 'e' || inKey == 'E' ) { mMoveDirection->mZ = 0; } else if( inKey == 'd' || inKey == 'D' ) { mMoveDirection->mZ = 0; } if( inKey == 'j' || inKey == 'J' ) { mMoveDirection->mX = 0; } else if( inKey == 'l' || inKey == 'L' ) { mMoveDirection->mX = 0; } if( inKey == 'i' || inKey == 'I' ) { mYMovement = 0; } else if( inKey == 'k' || inKey == 'K' ) { mYMovement = 0; } if( inKey == 's' || inKey == 'S' ) { mRotationOffset->mY = 0; } else if( inKey == 'f' || inKey == 'F' ) { mRotationOffset->mY = 0; } if( inKey == 'y' || inKey == 'Y' ) { mRotationOffset->mX = 0; } else if( inKey == 'h' || inKey == 'H' ) { mRotationOffset->mX = 0; } } inline void SceneNavigatorDisplayGL::specialKeyPressed( int inKey, int inX, int inY ) { } inline void SceneNavigatorDisplayGL::specialKeyReleased( int inKey, int inX, int inY ) { } inline void SceneNavigatorDisplayGL::fireRedraw() { unsigned long currentTimeS; unsigned long currentTimeMS; Time::getCurrentTime( ¤tTimeS, ¤tTimeMS ); unsigned long deltaMS = Time::getMillisecondsSince( mTimeLastRedrawS, mTimeLastRedrawMS ); mTimeLastRedrawS = currentTimeS; mTimeLastRedrawMS = currentTimeMS; // compute the number of units to move to maintain // a constant speed of mUnitsPerSecond double unitsToMove = mMoveUnitsPerSecond * ( deltaMS / 1000.0 ); double radiansToRotate = mRotateRadiansPerSecond * ( deltaMS / 1000.0 ); // scale our rotation offset Angle3D *scaledRotationOffset = new Angle3D( mRotationOffset ); scaledRotationOffset->scale( radiansToRotate ); // rotate the view in the super class rotateView( scaledRotationOffset ); delete scaledRotationOffset; Vector3D *move = new Vector3D( mMoveDirection ); // scale our move direction move->scale( unitsToMove ); Angle3D *rotation = new Angle3D( getViewOrientation() ); // only rotate movement direction about y axis // we don't want view y direction to affect the direction of movement rotation->mX = 0; rotation->mZ = 0; move->rotate( rotation ); delete rotation; // now add in y movement, scaled move->mY = mYMovement * unitsToMove; // move the view in the superclass moveView( move ); delete move; } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/SingleTextureGL.h0000640000175000017500000001117011435543334023370 0ustar pabspabs/* * Modification History * * 2001-September-15 Jason Rohrer * Created. * * 2005-February-21 Jason Rohrer * Added comments about channel ordering. * Created a cpp file for static init and longer function definitions. * * 2005-August-24 Jason Rohrer * Added control over texture wrapping. * * 2006-September-20 Jason Rohrer * Changed type of mTextureID to avoid compile warnings on MacOSX. * * 2009-September-9 Jason Rohrer * Added direct RGBA construction. * * 2009-November-5 Jason Rohrer * Added texture data replacement. * * 2010-April-20 Jason Rohrer * Reload all SingleTextures after GL context change. */ #ifndef SINGLE_TEXTURE_GL_INCLUDED #define SINGLE_TEXTURE_GL_INCLUDED #include #include #include #include "minorGems/graphics/Image.h" #include "minorGems/graphics/RGBAImage.h" #include "minorGems/util/SimpleVector.h" /** * A single-layer OpenGL 32-bit texture map. * * This is essentially a simplified version of TextureGL. * * @author Jason Rohrer */ class SingleTextureGL { public: /** * Constructs a texture map, specifying texture data. * * Note that this constructor can only be called * after a GL context has been setup. * * @param inImage the image to use as a source * for texture data. The image should have * 4 channels. Any extra channels are ignored, * and black is set into additional texture * channels if inImage has too few channels. * Must be destroyed by caller, and can be * destroyed as soon as this constructor returns. * Channels are ordered as RGBA. * Must be destroyed by caller. * @param inRepeat true to repeat (tile) texture. * Defaults to true. * * Note that width and height must each be powers of 2 and * not larger than 256 (for 3DFX compatability). Additionally, * for 3DFX compatability, the aspect ratio should not exceed 8:1. */ SingleTextureGL( Image *inImage, char inRepeat = true ); /** * Specifies texture data as rgba bytes. */ SingleTextureGL( unsigned char *inRGBA, unsigned int inWidth, unsigned int inHeight, char inRepeat = true ); /** * The OpenGL texture is deleted when the SingleTextureGL object is * destroyed. */ ~SingleTextureGL(); /** * Replaces data in a texture that's already been set. * Dimensions must match original dimensions. */ void replaceTextureData( unsigned char *inRGBA, unsigned int inWidth, unsigned int inHeight ); /** * Sets the data for this texture. * * @param inImage the image to use as a source * for texture data. The image should have * 4 channels. Any extra channels are ignored, * and black is set into additional texture * channels if inImage has too few channels. * Must be destroyed by caller, and can be * destroyed as soon as this constructor returns. * Channels are ordered as RGBA. * Must be destroyed by caller. * * Note that width and height must each be powers of 2 and * not larger than 256 (for 3DFX compatability). Additionally, * for 3DFX compatability, the aspect ratio should not exceed 8:1. */ void setTextureData( Image *inImage ); /** * Sets texture data as rgba bytes. */ void setTextureData( unsigned char *inRGBA, unsigned int inWidth, unsigned int inHeight ); /** * Enables this texture. */ void enable(); /** * Disables this texture and all of its layers. */ void disable(); // tell all textures about a GL context change so they can reload // int texture memory static void contextChanged(); private: char mRepeat; GLuint mTextureID; // in case of context switch where we need to reload our texture unsigned char *mRGBABackup; unsigned int mWidthBackup; unsigned int mHeightBackup; void reloadFromBackup(); static SimpleVector sAllLoadedTextures; }; inline void SingleTextureGL::enable() { glEnable( GL_TEXTURE_2D ); glBindTexture( GL_TEXTURE_2D, mTextureID ); int error = glGetError(); if( error != GL_NO_ERROR ) { // error printf( "Error binding texture id %d, error = %d\n", (int)mTextureID, error ); } } inline void SingleTextureGL::disable() { glDisable( GL_TEXTURE_2D ); } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/ScreenGL_SDL.cpp0000640000175000017500000007270411435543334023054 0ustar pabspabs/* * Modification History * * 2008-October-27 Jason Rohrer * Created. Copied structure from GLUT version (ScreenGL.cpp). * * 2009-March-19 Jason Rohrer * UNICODE support for keyboard input of symbols. * * 2010-March-17 Jason Rohrer * Support for Ctrl, Alt, and Meta. * * 2010-April-6 Jason Rohrer * Blocked event passing to handlers that were added by event. * * 2010-April-8 Jason Rohrer * Added post-redraw events. * Don't treat wheel events as mouse clicks. * * 2010-April-9 Jason Rohrer * Checks for closest matching resolution. * * 2010-April-20 Jason Rohrer * Alt-Enter to leave fullscreen mode. * Reload all SingleTextures after GL context change. * * 2010-May-7 Jason Rohrer * Mapped window close button to ESC key. * Extended ASCII. * * 2010-May-12 Jason Rohrer * Use full 8 lower bits of unicode to support extended ASCII. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. * * 2010-May-19 Jason Rohrer * Added support for 1-bit stencil buffer. * * 2010-May-21 Jason Rohrer * Mapped ctrl-q and alt-q to ESC key. * * 2010-August-26 Jason Rohrer * Fixed a parens warning. */ #include "ScreenGL.h" #include "SingleTextureGL.h" #include #include #include #include #include #include #include "minorGems/util/stringUtils.h" #include "minorGems/util/log/AppLog.h" /* ScreenGL to be accessed by callback functions. * * Note that this is a bit of a hack, but the callbacks * require a C-function (not a C++ member) and have fixed signatures, * so there's no way to pass the current screen into the functions. * * This hack prevents multiple instances of the ScreenGL class from * being used simultaneously. * * Even worse for SLD, because this hack is carried over from GLUT. * SDL doesn't even require C callbacks (you provide the event loop). */ ScreenGL *currentScreenGL; // maps SDL-specific special (non-ASCII) key-codes (SDLK) to minorGems key // codes (MG_KEY) int mapSDLSpecialKeyToMG( int inSDLKey ); // for ascii key char mapSDLKeyToASCII( int inSDLKey ); // prototypes /* void callbackResize( int inW, int inH ); void callbackKeyboard( unsigned char inKey, int inX, int inY ); void callbackMotion( int inX, int inY ); void callbackPassiveMotion( int inX, int inY ); void callbackMouse( int inButton, int inState, int inX, int inY ); void callbackDisplay(); void callbackIdle(); */ ScreenGL::ScreenGL( int inWide, int inHigh, char inFullScreen, const char *inWindowName, KeyboardHandlerGL *inKeyHandler, MouseHandlerGL *inMouseHandler, SceneHandlerGL *inSceneHandler ) : mWide( inWide ), mHigh( inHigh ), mImageWide( inWide ), mImageHigh( inHigh ), mFullScreen( inFullScreen ), m2DMode( false ), mViewPosition( new Vector3D( 0, 0, 0 ) ), mViewOrientation( new Angle3D( 0, 0, 0 ) ), mMouseHandlerVector( new SimpleVector() ), mKeyboardHandlerVector( new SimpleVector() ), mSceneHandlerVector( new SimpleVector() ), mRedrawListenerVector( new SimpleVector() ) { // add handlers if NULL (the default) was not passed in for them if( inMouseHandler != NULL ) { addMouseHandler( inMouseHandler ); } if( inKeyHandler != NULL ) { addKeyboardHandler( inKeyHandler ); } if( inSceneHandler != NULL ) { addSceneHandler( inSceneHandler ); } mStartedFullScreen = mFullScreen; setupSurface(); SDL_WM_SetCaption( inWindowName, NULL ); // turn off repeat SDL_EnableKeyRepeat( 0, 0 ); SDL_EnableUNICODE( true ); } ScreenGL::~ScreenGL() { delete mViewPosition; delete mViewOrientation; delete mRedrawListenerVector; delete mMouseHandlerVector; delete mKeyboardHandlerVector; delete mSceneHandlerVector; } char screenGLStencilBufferSupported = false; void ScreenGL::setupSurface() { SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); int flags = SDL_OPENGL; if( mFullScreen ) { flags = flags | SDL_FULLSCREEN; } // check for available modes SDL_Rect** modes; AppLog::getLog()->logPrintf( Log::INFO_LEVEL, "Checking if requested video mode (%dx%d) is available", mWide, mHigh ); // Get available fullscreen/hardware modes modes = SDL_ListModes( NULL, flags); // Check if there are any modes available if( modes == NULL ) { AppLog::criticalError( "ERROR: No video modes available"); exit(-1); } // Check if our resolution is restricted if( modes == (SDL_Rect**)-1 ) { AppLog::info( "All resolutions available" ); } else{ // Print valid modes char match = false; AppLog::info( "Available video modes:" ); for( int i=0; modes[i]; ++i ) { AppLog::getLog()->logPrintf( Log::DETAIL_LEVEL, " %d x %d\n", modes[i]->w, modes[i]->h ); if( mWide == modes[i]->w && mHigh == modes[i]->h ) { AppLog::info( " ^^^^ this mode matches requested mode" ); match = true; } } if( !match ) { AppLog::warning( "Warning: No match for requested video mode" ); AppLog::info( "Trying to find the closest match" ); int bestDistance = 99999999; int bestIndex = -1; for( int i=0; modes[i]; ++i ) { int distance = (int)( fabs( modes[i]->w - mWide ) + fabs( modes[i]->h - mHigh ) ); if( distance < bestDistance ) { bestIndex = i; bestDistance = distance; } } AppLog::getLog()->logPrintf( Log::INFO_LEVEL, "Picking closest available resolution, %d x %d\n", modes[bestIndex]->w, modes[bestIndex]->h ); mWide = modes[bestIndex]->w; mHigh = modes[bestIndex]->h; } } // 1-bit stencil buffer SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, 1 ); // current color depth SDL_Surface *screen = SDL_SetVideoMode( mWide, mHigh, 0, flags); if ( screen == NULL ) { printf( "Couldn't set %dx%d GL video mode: %s\n", mWide, mHigh, SDL_GetError() ); } int setStencilSize; SDL_GL_GetAttribute( SDL_GL_STENCIL_SIZE, &setStencilSize ); if( setStencilSize > 0 ) { // we have a stencil buffer screenGLStencilBufferSupported = true; } glEnable( GL_DEPTH_TEST ); glEnable( GL_CULL_FACE ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glCullFace( GL_BACK ); glFrontFace( GL_CCW ); } void ScreenGL::start() { currentScreenGL = this; // call our resize callback (GLUT used to do this for us when the // window was created) callbackResize( mWide, mHigh ); // main loop while( true ) { callbackDisplay(); // handle all pending events SDL_Event event; while( SDL_PollEvent( &event ) ) { SDLMod mods = SDL_GetModState(); // alt-enter, toggle fullscreen (but only if we started there, // to prevent window content centering issues due to mWidth and // mHeight changes mid-game) if( mStartedFullScreen && event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_RETURN && ( ( mods & KMOD_META ) || ( mods & KMOD_ALT ) ) ) { printf( "Toggling fullscreen\n" ); mFullScreen = !mFullScreen; setupSurface(); callbackResize( mWide, mHigh ); // reload all textures into OpenGL SingleTextureGL::contextChanged(); } // map CTRL-q to ESC // 17 is "DC1" which is ctrl-z on some platforms else if( event.type == SDL_KEYDOWN && ( ( event.key.keysym.sym == SDLK_q && ( ( mods & KMOD_META ) || ( mods & KMOD_ALT ) || ( mods & KMOD_CTRL ) ) ) || ( event.key.keysym.unicode & 0xFF == 17 ) ) ) { // map to 27, escape int mouseX, mouseY; SDL_GetMouseState( &mouseX, &mouseY ); callbackKeyboard( 27, mouseX, mouseY ); } else { switch( event.type ) { case SDL_QUIT: { // map to 27, escape int mouseX, mouseY; SDL_GetMouseState( &mouseX, &mouseY ); callbackKeyboard( 27, mouseX, mouseY ); } break; case SDL_KEYDOWN: case SDL_KEYUP: { int mouseX, mouseY; SDL_GetMouseState( &mouseX, &mouseY ); // check if special key int mgKey = mapSDLSpecialKeyToMG( event.key.keysym.sym ); if( mgKey != 0 ) { if( event.type == SDL_KEYDOWN ) { callbackSpecialKeyboard( mgKey, mouseX, mouseY ); } else { callbackSpecialKeyboardUp( mgKey, mouseX, mouseY ); } } else { unsigned char asciiKey; // try unicode first, if 8-bit clean (extended ASCII) if( ( event.key.keysym.unicode & 0xFF00 ) == 0 ) { asciiKey = event.key.keysym.unicode & 0xFF; } else { // else unicode-to-ascii failed // fall back asciiKey = mapSDLKeyToASCII( event.key.keysym.sym ); } if( asciiKey != 0 ) { // shift and caps cancel each other if( ( ( event.key.keysym.mod & KMOD_SHIFT ) && !( event.key.keysym.mod & KMOD_CAPS ) ) || ( !( event.key.keysym.mod & KMOD_SHIFT ) && ( event.key.keysym.mod & KMOD_CAPS ) ) ) { asciiKey = toupper( asciiKey ); } if( event.type == SDL_KEYDOWN ) { callbackKeyboard( asciiKey, mouseX, mouseY ); } else { callbackKeyboardUp( asciiKey, mouseX, mouseY ); } } } } break; case SDL_MOUSEMOTION: if( event.motion.state & SDL_BUTTON( 1 ) || event.motion.state & SDL_BUTTON( 2 ) || event.motion.state & SDL_BUTTON( 3 ) ) { callbackMotion( event.motion.x, event.motion.y ); } else { callbackPassiveMotion( event.motion.x, event.motion.y ); } break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: callbackMouse( event.button.button, event.button.state, event.button.x, event.button.y ); break; } } } } } void ScreenGL::switchTo2DMode() { m2DMode = true; } void ScreenGL::setFullScreen() { //glutFullScreen(); } void ScreenGL::changeWindowSize( int inWidth, int inHeight ) { //glutReshapeWindow( inWidth, inHeight ); } void ScreenGL::applyViewTransform() { // compute view angle // default angle is 90, but we want to force a 1:1 aspect ratio to avoid // distortion. // If our screen's width is different than its height, we need to decrease // the view angle so that the angle coresponds to the smaller dimension. // This keeps the zoom factor constant in the smaller dimension. // Of course, because of the way perspective works, only one Z-slice // will have a constant zoom factor // The zSlice variable sets the distance of this slice from the picture // plane double zSlice = .31; double maxDimension = mWide; if( mHigh > mWide ) { maxDimension = mHigh; } double aspectDifference = fabs( mWide / 2 - mHigh / 2 ) / maxDimension; // default angle is 90 degrees... half the angle is PI/4 double angle = atan( tan( M_PI / 4 ) + aspectDifference / zSlice ); // double it to get the full angle angle *= 2; // convert to degrees angle = 360 * angle / ( 2 * M_PI ); // set up the projection matrix glMatrixMode( GL_PROJECTION ); glLoadIdentity(); //gluPerspective( 90, mWide / mHigh, 1, 9999 ); gluPerspective( angle, 1, 1, 9999 ); // set up the model view matrix glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); // create default view and up vectors, // then rotate them by orientation angle Vector3D *viewDirection = new Vector3D( 0, 0, 1 ); Vector3D *upDirection = new Vector3D( 0, 1, 0 ); viewDirection->rotate( mViewOrientation ); upDirection->rotate( mViewOrientation ); // get a point out in front of us in the view direction viewDirection->add( mViewPosition ); // look at takes a viewer position, // a point to look at, and an up direction gluLookAt( mViewPosition->mX, mViewPosition->mY, mViewPosition->mZ, viewDirection->mX, viewDirection->mY, viewDirection->mZ, upDirection->mX, upDirection->mY, upDirection->mZ ); delete viewDirection; delete upDirection; } void callbackResize( int inW, int inH ) { ScreenGL *s = currentScreenGL; s->mWide = inW; s->mHigh = inH; int bigDimension = s->mImageWide; if( bigDimension < s->mImageHigh ) { bigDimension = s->mImageHigh; } int excessW = s->mWide - bigDimension; int excessH = s->mHigh - bigDimension; // viewport is square of biggest image dimension, centered on screen glViewport( excessW / 2, excessH / 2, bigDimension, bigDimension ); } void callbackKeyboard( unsigned char inKey, int inX, int inY ) { char someFocused = currentScreenGL->isKeyboardHandlerFocused(); int h; // flag those that exist right now // because handlers might remove themselves or add new handlers, // and we don't want to fire to those that weren't present when // callback was called for( h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); handler->mHandlerFlagged = true; } // fire to all handlers for( h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); if( handler->mHandlerFlagged ) { // if some are focused, only fire to this handler if it is one // of the focused handlers if( !someFocused || handler->isFocused() ) { handler->keyPressed( inKey, inX, inY ); } } } // deflag for next time for( h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); handler->mHandlerFlagged = false; } } void callbackKeyboardUp( unsigned char inKey, int inX, int inY ) { char someFocused = currentScreenGL->isKeyboardHandlerFocused(); int h; // flag those that exist right now // because handlers might remove themselves or add new handlers, // and we don't want to fire to those that weren't present when // callback was called for( h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); handler->mHandlerFlagged = true; } // fire to all handlers for( h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); if( handler->mHandlerFlagged ) { // if some are focused, only fire to this handler if it is one // of the focused handlers if( !someFocused || handler->isFocused() ) { handler->keyReleased( inKey, inX, inY ); } } } // deflag for next time for( h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); handler->mHandlerFlagged = false; } } void callbackSpecialKeyboard( int inKey, int inX, int inY ) { char someFocused = currentScreenGL->isKeyboardHandlerFocused(); int h; // flag those that exist right now // because handlers might remove themselves or add new handlers, // and we don't want to fire to those that weren't present when // callback was called for( h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); handler->mHandlerFlagged = true; } // fire to all handlers for( h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); if( handler->mHandlerFlagged ) { // if some are focused, only fire to this handler if it is one // of the focused handlers if( !someFocused || handler->isFocused() ) { handler->specialKeyPressed( inKey, inX, inY ); } } } // deflag for next time for( h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); handler->mHandlerFlagged = false; } } void callbackSpecialKeyboardUp( int inKey, int inX, int inY ) { char someFocused = currentScreenGL->isKeyboardHandlerFocused(); int h; // flag those that exist right now // because handlers might remove themselves or add new handlers, // and we don't want to fire to those that weren't present when // callback was called for( h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); handler->mHandlerFlagged = true; } // fire to all handlers for( h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); if( handler->mHandlerFlagged ) { // if some are focused, only fire to this handler if it is one // of the focused handlers if( !someFocused || handler->isFocused() ) { handler->specialKeyReleased( inKey, inX, inY ); } } } // deflag for next time for( h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); handler->mHandlerFlagged = false; } } void callbackMotion( int inX, int inY ) { // fire to all handlers int h; // flag those that exist right now // because handlers might remove themselves or add new handlers, // and we don't want to fire to those that weren't present when // callback was called for( h=0; hmMouseHandlerVector->size(); h++ ) { MouseHandlerGL *handler = *( currentScreenGL->mMouseHandlerVector->getElement( h ) ); handler->mHandlerFlagged = true; } for( h=0; hmMouseHandlerVector->size(); h++ ) { MouseHandlerGL *handler = *( currentScreenGL->mMouseHandlerVector->getElement( h ) ); if( handler->mHandlerFlagged ) { handler->mouseDragged( inX, inY ); } } // deflag for next time for( h=0; hmMouseHandlerVector->size(); h++ ) { MouseHandlerGL *handler = *( currentScreenGL->mMouseHandlerVector->getElement( h ) ); handler->mHandlerFlagged = false; } } void callbackPassiveMotion( int inX, int inY ) { // fire to all handlers int h; // flag those that exist right now // because handlers might remove themselves or add new handlers, // and we don't want to fire to those that weren't present when // callback was called for( h=0; hmMouseHandlerVector->size(); h++ ) { MouseHandlerGL *handler = *( currentScreenGL->mMouseHandlerVector->getElement( h ) ); handler->mHandlerFlagged = true; } for( h=0; hmMouseHandlerVector->size(); h++ ) { MouseHandlerGL *handler = *( currentScreenGL->mMouseHandlerVector->getElement( h ) ); if( handler->mHandlerFlagged ) { handler->mouseMoved( inX, inY ); } } // deflag for next time for( h=0; hmMouseHandlerVector->size(); h++ ) { MouseHandlerGL *handler = *( currentScreenGL->mMouseHandlerVector->getElement( h ) ); handler->mHandlerFlagged = false; } } void callbackMouse( int inButton, int inState, int inX, int inY ) { // ignore wheel events if( inButton == SDL_BUTTON_WHEELUP || inButton == SDL_BUTTON_WHEELDOWN ) { return; } // fire to all handlers int h; // flag those that exist right now // because handlers might remove themselves or add new handlers, // and we don't want to fire to those that weren't present when // callbackMouse was called for( h=0; hmMouseHandlerVector->size(); h++ ) { MouseHandlerGL *handler = *( currentScreenGL->mMouseHandlerVector->getElement( h ) ); handler->mHandlerFlagged = true; } for( h=0; hmMouseHandlerVector->size(); h++ ) { MouseHandlerGL *handler = *( currentScreenGL->mMouseHandlerVector->getElement( h ) ); if( handler->mHandlerFlagged ) { handler->mouseMoved( inX, inY ); if( inState == SDL_PRESSED ) { handler->mousePressed( inX, inY ); } else if( inState == SDL_RELEASED ) { handler->mouseReleased( inX, inY ); } else { printf( "Error: Unknown mouse state received from SDL\n" ); } } } // deflag for next time for( h=0; hmMouseHandlerVector->size(); h++ ) { MouseHandlerGL *handler = *( currentScreenGL->mMouseHandlerVector->getElement( h ) ); handler->mHandlerFlagged = false; } } void callbackDisplay() { ScreenGL *s = currentScreenGL; glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // fire to all redraw listeners // do this first so that they can update our view transform // this makes control much more responsive for( int r=0; rmRedrawListenerVector->size(); r++ ) { RedrawListenerGL *listener = *( s->mRedrawListenerVector->getElement( r ) ); listener->fireRedraw(); } if( ! s->m2DMode ) { // apply our view transform s->applyViewTransform(); } // fire to all handlers for( int h=0; hmSceneHandlerVector->size(); h++ ) { SceneHandlerGL *handler = *( currentScreenGL->mSceneHandlerVector->getElement( h ) ); handler->drawScene(); } for( int r=0; rmRedrawListenerVector->size(); r++ ) { RedrawListenerGL *listener = *( s->mRedrawListenerVector->getElement( r ) ); listener->postRedraw(); } SDL_GL_SwapBuffers(); } void callbackIdle() { //glutPostRedisplay(); } int mapSDLSpecialKeyToMG( int inSDLKey ) { switch( inSDLKey ) { case SDLK_F1: return MG_KEY_F1; case SDLK_F2: return MG_KEY_F2; case SDLK_F3: return MG_KEY_F3; case SDLK_F4: return MG_KEY_F4; case SDLK_F5: return MG_KEY_F5; case SDLK_F6: return MG_KEY_F6; case SDLK_F7: return MG_KEY_F7; case SDLK_F8: return MG_KEY_F8; case SDLK_F9: return MG_KEY_F9; case SDLK_F10: return MG_KEY_F10; case SDLK_F11: return MG_KEY_F11; case SDLK_F12: return MG_KEY_F12; case SDLK_LEFT: return MG_KEY_LEFT; case SDLK_UP: return MG_KEY_UP; case SDLK_RIGHT: return MG_KEY_RIGHT; case SDLK_DOWN: return MG_KEY_DOWN; case SDLK_PAGEUP: return MG_KEY_PAGE_UP; case SDLK_PAGEDOWN: return MG_KEY_PAGE_DOWN; case SDLK_HOME: return MG_KEY_HOME; case SDLK_END: return MG_KEY_END; case SDLK_INSERT: return MG_KEY_INSERT; case SDLK_RSHIFT: return MG_KEY_RSHIFT; case SDLK_LSHIFT: return MG_KEY_LSHIFT; case SDLK_RCTRL: return MG_KEY_RCTRL; case SDLK_LCTRL: return MG_KEY_LCTRL; case SDLK_RALT: return MG_KEY_RALT; case SDLK_LALT: return MG_KEY_LALT; case SDLK_RMETA: return MG_KEY_RMETA; case SDLK_LMETA: return MG_KEY_LMETA; default: return 0; } } char mapSDLKeyToASCII( int inSDLKey ) { // map world keys (SDLK_WORLD_X) directly to ASCII if( inSDLKey >= 160 && inSDLKey <=255 ) { return inSDLKey; } switch( inSDLKey ) { case SDLK_UNKNOWN: return 0; case SDLK_BACKSPACE: return 8; case SDLK_TAB: return 9; case SDLK_CLEAR: return 12; case SDLK_RETURN: return 13; case SDLK_PAUSE: return 19; case SDLK_ESCAPE: return 27; case SDLK_SPACE: return ' '; case SDLK_EXCLAIM: return '!'; case SDLK_QUOTEDBL: return '"'; case SDLK_HASH: return '#'; case SDLK_DOLLAR: return '$'; case SDLK_AMPERSAND: return '&'; case SDLK_QUOTE: return '\''; case SDLK_LEFTPAREN: return '('; case SDLK_RIGHTPAREN: return ')'; case SDLK_ASTERISK: return '*'; case SDLK_PLUS: return '+'; case SDLK_COMMA: return ','; case SDLK_MINUS: return '-'; case SDLK_PERIOD: return '.'; case SDLK_SLASH: return '/'; case SDLK_0: return '0'; case SDLK_1: return '1'; case SDLK_2: return '2'; case SDLK_3: return '3'; case SDLK_4: return '4'; case SDLK_5: return '5'; case SDLK_6: return '6'; case SDLK_7: return '7'; case SDLK_8: return '8'; case SDLK_9: return '9'; case SDLK_COLON: return ':'; case SDLK_SEMICOLON: return ';'; case SDLK_LESS: return '<'; case SDLK_EQUALS: return '='; case SDLK_GREATER: return '>'; case SDLK_QUESTION: return '?'; case SDLK_AT: return '@'; case SDLK_LEFTBRACKET: return '['; case SDLK_BACKSLASH: return '\\'; case SDLK_RIGHTBRACKET: return ']'; case SDLK_CARET: return '^'; case SDLK_UNDERSCORE: return '_'; case SDLK_BACKQUOTE: return '`'; case SDLK_a: return 'a'; case SDLK_b: return 'b'; case SDLK_c: return 'c'; case SDLK_d: return 'd'; case SDLK_e: return 'e'; case SDLK_f: return 'f'; case SDLK_g: return 'g'; case SDLK_h: return 'h'; case SDLK_i: return 'i'; case SDLK_j: return 'j'; case SDLK_k: return 'k'; case SDLK_l: return 'l'; case SDLK_m: return 'm'; case SDLK_n: return 'n'; case SDLK_o: return 'o'; case SDLK_p: return 'p'; case SDLK_q: return 'q'; case SDLK_r: return 'r'; case SDLK_s: return 's'; case SDLK_t: return 't'; case SDLK_u: return 'u'; case SDLK_v: return 'v'; case SDLK_w: return 'w'; case SDLK_x: return 'x'; case SDLK_y: return 'y'; case SDLK_z: return 'z'; case SDLK_DELETE: return 127; case SDLK_WORLD_0: default: return 0; } } between-6+dfsg1.orig/minorGems/graphics/openGL/TestSceneHandlerGL.h0000640000175000017500000000275011435543334023765 0ustar pabspabs/* * Modification History * * 2001-August-29 Jason Rohrer * Created. * * 2001-August-30 Jason Rohrer * Added random triangels for testing. */ #ifndef TEST_SCENE_HANDLER_GL_INCLUDED #define TEST_SCENE_HANDLER_GL_INCLUDED #include #include "SceneHandlerGL.h" #include "minorGems/util/random/StdRandomSource.h" /** * A test scene implementation. * * @author Jason Rohrer */ class TestSceneHandlerGL : public SceneHandlerGL { public: // implements the SceneHandlerGL interface virtual void drawScene(); }; void TestSceneHandlerGL::drawScene() { glDisable( GL_TEXTURE_2D ); glDisable( GL_CULL_FACE ); StdRandomSource source( 0 ); glBegin( GL_TRIANGLES ); { for( int i=0; i<10; i++ ) { glColor4f( source.getRandomFloat(), source.getRandomFloat(), source.getRandomFloat(), 1.0 ); glVertex3f( source.getRandomFloat() * 100, source.getRandomFloat() * 100, source.getRandomFloat() * 100 ); glColor4f( source.getRandomFloat(), source.getRandomFloat(), source.getRandomFloat(), 1.0 ); glVertex3f( source.getRandomFloat() * 100, source.getRandomFloat() * 100, source.getRandomFloat() * 100 ); glColor4f( source.getRandomFloat(), source.getRandomFloat(), source.getRandomFloat(), 1.0 ); glVertex3f( source.getRandomFloat() * 100, source.getRandomFloat() * 100, source.getRandomFloat() * 100 ); } } glEnd(); } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/ObjectGL.h0000640000175000017500000001172511435543334022002 0ustar pabspabs/* * Modification History * * 2000-December-20 Jason Rohrer * Created. * * 2001-January-6 Jason Rohrer * Added some missing includes. * * 2001-January-16 Jason Rohrer * Changed to use a Transform3D instead of Vectors, Angles, and scales for * each primitive in the object. Changed draw() function to take a Transform3D. * Fixed a memory leak in the draw() function. * * 2001-March-14 Jason Rohrer * Added support for paramatization and temporal animations. */ #ifndef OBJECT_GL_INCLUDED #define OBJECT_GL_INCLUDED #include #include "PrimitiveGL.h" #include "LightingGL.h" #include "minorGems/math/geometry/Transform3D.h" #include "minorGems/graphics/3d/Object3D.h" /** * OpenGL object. * * Comprised of a collection of primitives. * * @author Jason Rohrer */ class ObjectGL { public: /** * Constructs an Object. * * No parameters are copied, so they should not be destroyed * or re-accessed by caller. All are destroyed when the * object is destroyed. * * @param inObject the Object3D to base this GL version on. */ ObjectGL( Object3D *inObject ); ~ObjectGL(); /** * Draws the object. * * @param inTransform the transform to apply to the object before * drawing it. * @param inLighting the lighting to use when drawing the object. */ void draw( Transform3D *inTransform, LightingGL *inLighting ); /** * Gets the number of parameters associated with this object. * * @return the number of parameters. */ virtual int getNumParameters(); /** * Gets the number of animations associated with this object. * * @return the number of animations. */ virtual int getNumAnimations(); /** * Sets a parameter for this object. * * @param inParameterIndex the index of the parameter to set. * If an index for a non-existing parameter is specified, * this call has no effect. * @param inValue the value to set the parameter to, in [-1, 1]. * The default value for all parameters is 0. */ virtual void setParameter( int inParameterIndex, double inValue ); /** * Gets a parameter for this object. * * @param inParameterIndex the index of the parameter to get. * If an index for a non-existing parameter is specified, * 0 is returned. * * @return the value of the parameter, in [-1, 1]. * The default value for all parameters is 0. */ virtual double getParameter( int inParameterIndex ); /** * Steps this object forward in time. * * @param inStepSize the size of the timestep to take. */ virtual void step( double inStepSize ); /** * Starts a temporal animation of this object. * The animation progresses as step() is called repeatedly. * If called for a non-existent animation or for one that is * already running, this function has no effect. */ virtual void startAnimation( int inAnimationIndex ); /** * Stops a temporal animation of this object. If called * for a non-existent animation or for one that is not currently * running, this function has no effect. */ virtual void stopAnimation( int inAnimationIndex ); private: Object3D *mObject; // GL versions of the primitives PrimitiveGL **mPrimitives; }; inline ObjectGL::ObjectGL( Object3D *inObject ) : mObject( inObject ) { mPrimitives = new PrimitiveGL*[ mObject->mNumPrimitives ]; for( int i=0; imNumPrimitives; i++ ) { mPrimitives[i] = new PrimitiveGL( mObject->mPrimitives[i] ); } } inline ObjectGL::~ObjectGL() { for( int i=0; imNumPrimitives; i++ ) { delete mPrimitives[i]; } delete [] mPrimitives; delete mObject; } inline void ObjectGL::draw( Transform3D *inTransform, LightingGL *inLighting ) { for( int i=0; imNumPrimitives; i++ ) { // need to transform the position of primitive within object // copy the transform for this primitive Transform3D *primTransform = new Transform3D( mObject->mTransform[i] ); // add the object transform to the end of it primTransform->transform( inTransform ); mPrimitives[i]->draw( primTransform, inLighting ); delete primTransform; } } // these just pass the function call on to the underlying Object3D inline int ObjectGL::getNumParameters() { return mObject->getNumParameters(); } inline int ObjectGL::getNumAnimations() { return mObject->getNumAnimations(); } inline void ObjectGL::setParameter( int inParameterIndex, double inValue ) { mObject->setParameter( inParameterIndex, inValue ); } inline double ObjectGL::getParameter( int inParameterIndex ) { return mObject->getParameter( inParameterIndex ); } inline void ObjectGL::step( double inStepSize ) { mObject->step( inStepSize ); } inline void ObjectGL::startAnimation( int inAnimationIndex ) { mObject->startAnimation( inAnimationIndex ); } inline void ObjectGL::stopAnimation( int inAnimationIndex ) { mObject->stopAnimation( inAnimationIndex ); } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/testNavigatorGLcompile0000750000175000017500000000030211435543334024540 0ustar pabspabsg++ -g -o testNavigatorGL -I/usr/X11R6/include -I../../.. -L/usr/X11R6/lib -lGL -lglut -lGLU -lX11 -lXi -lXext -lXmu ScreenGL.cpp testNavigatorGL.cpp ../../../minorGems/io/linux/TypeIOLinux.cpp between-6+dfsg1.orig/minorGems/graphics/openGL/MultiLightingGL.h0000640000175000017500000000441511435543334023352 0ustar pabspabs/* * Modification History * * 2000-December-20 Jason Rohrer * Created. */ #ifndef MULTI_LIGHTING_GL_INCLUDED #define MULTI_LIGHTING_GL_INCLUDED #include #include "LightingGL.h" #include "minorGems/util/SimpleVector.h" /** * A LightingGL implementation that contains a collection of * LightingGLs. * * @author Jason Rohrer */ class MultiLightingGL : public LightingGL { public: /** * Constructs a MultiLighting. */ MultiLightingGL(); ~MultiLightingGL(); /** * Adds a lighting to this MultiLighting. * * @param inLighting lighting to add. Is not * destroyed when the MultiLighting is destroyed. */ void addLighting( LightingGL *inLighting ); /** * Removes a lighting to this MultiLighting. * * @param inLighting lighting to remove. */ void removeLighting( LightingGL *inLighting ); // implements LightingGL interface void getLighting( Vector3D *inPoint, Vector3D *inNormal, Color *outColor ); private: SimpleVector *mLightingVector; }; inline MultiLightingGL::MultiLightingGL() : mLightingVector( new SimpleVector() ) { } inline MultiLightingGL::~MultiLightingGL() { delete mLightingVector; } inline void MultiLightingGL::addLighting( LightingGL *inLighting ) { mLightingVector->push_back( inLighting ); } inline void MultiLightingGL::removeLighting( LightingGL *inLighting ) { mLightingVector->deleteElement( inLighting ); } inline void MultiLightingGL::getLighting( Vector3D *inPoint, Vector3D *inNormal, Color *outColor ) { int numLightings = mLightingVector->size(); outColor->r = 0; outColor->g = 0; outColor->b = 0; // sum lighting contributions from each lighting for( int i=0; igetElement( i ) ); thisLighting->getLighting( inPoint, inNormal, tempColor ); outColor->r += tempColor->r; outColor->g += tempColor->g; outColor->b += tempColor->b; delete tempColor; } // clip color components: if( outColor->r > 1.0 ) { outColor->r = 1.0; } if( outColor->g > 1.0 ) { outColor->g = 1.0; } if( outColor->b > 1.0 ) { outColor->b = 1.0; } } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/DirectionLightingGL.h0000640000175000017500000000331011435543334024171 0ustar pabspabs/* * Modification History * * 2000-December-20 Jason Rohrer * Created. */ #ifndef DIRECTION_LIGHTING_GL_INCLUDED #define DIRECTION_LIGHTING_GL_INCLUDED #include #include "LightingGL.h" /** * A LightingGL implementation with a single point light source * at distance infinity. * * @author Jason Rohrer */ class DirectionLightingGL : public LightingGL { public: /** * Constructs a DirectionLighting. * * @param inColor color of lighting for a surface * that is facing directly into the light source. * Is not copied, so cannot be accessed again by caller. * @param inDirection incoming direction of light source. * Is not copied, so cannot be accessed again by caller. */ DirectionLightingGL( Color *inColor, Vector3D *inDirection ); ~DirectionLightingGL(); // implements LightingGL interface void getLighting( Vector3D *inPoint, Vector3D *inNormal, Color *outColor ); private: Color *mColor; // direction pointing *towards* light source Vector3D *mDirection; }; inline DirectionLightingGL::DirectionLightingGL( Color *inColor, Vector3D *inDirection ) : mColor( inColor ), mDirection( inDirection ) { // reverse the passed-in direction mDirection->scale( -1 ); } inline DirectionLightingGL::~DirectionLightingGL() { delete mColor; delete mDirection; } inline void DirectionLightingGL::getLighting( Vector3D *inPoint, Vector3D *inNormal, Color *outColor ) { double dot = inNormal->dot( mDirection ); if( dot > 0 ) { outColor->r = mColor->r * dot; outColor->g = mColor->g * dot; outColor->b = mColor->b * dot; } else { outColor->r = 0; outColor->g = 0; outColor->b = 0; } } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/KeyboardHandlerGL.h0000640000175000017500000001053511435543334023630 0ustar pabspabs/* * Modification History * * 2000-December-19 Jason Rohrer * Created. * * 2001-February-4 Jason Rohrer * Added key release functions. * * 2001-October-29 Jason Rohrer * Added fuction for querying a handler's focus. * * 2008-October-27 Jason Rohrer * Switched to implementation-independent keycodes. * * 2010-March-17 Jason Rohrer * Support for Ctrl, Alt, and Meta. * * 2010-April-6 Jason Rohrer * Blocked event passing to handlers that were added by event. */ #ifndef KEYBOARD_HANDLER_GL_INCLUDED #define KEYBOARD_HANDLER_GL_INCLUDED // special key codes #define MG_KEY_F1 0x0001 #define MG_KEY_F2 0x0002 #define MG_KEY_F3 0x0003 #define MG_KEY_F4 0x0004 #define MG_KEY_F5 0x0005 #define MG_KEY_F6 0x0006 #define MG_KEY_F7 0x0007 #define MG_KEY_F8 0x0008 #define MG_KEY_F9 0x0009 #define MG_KEY_F10 0x000A #define MG_KEY_F11 0x000B #define MG_KEY_F12 0x000C #define MG_KEY_LEFT 0x0064 #define MG_KEY_UP 0x0065 #define MG_KEY_RIGHT 0x0066 #define MG_KEY_DOWN 0x0067 #define MG_KEY_PAGE_UP 0x0068 #define MG_KEY_PAGE_DOWN 0x0069 #define MG_KEY_HOME 0x006A #define MG_KEY_END 0x006B #define MG_KEY_INSERT 0x006C #define MG_KEY_RSHIFT 0x0070 #define MG_KEY_LSHIFT 0x0071 #define MG_KEY_RCTRL 0x0072 #define MG_KEY_LCTRL 0x0073 #define MG_KEY_RALT 0x0074 #define MG_KEY_LALT 0x0075 #define MG_KEY_RMETA 0x0076 #define MG_KEY_LMETA 0x0077 /** * Interface for an object that can field OpenGL keystrokes. * * @author Jason Rohrer */ class KeyboardHandlerGL { public: virtual ~KeyboardHandlerGL() { } /** * Gets whether this handler is focused (in other words, * whether this handler wants to reserve keyboard * events for itself). * * If no registered handler is focused, then all * registered handlers receive keyboard events. However, * if some handlers are focused, then only focused handlers * receive keyboard events. * * Note that in general, handlers should be unfocused. * A default implementation is included in this interface, * so handlers that do not care about focus can ignore * this function. * * @return true iff this handler is focused. */ virtual char isFocused(); /** * Callback function for when an ASCII-representable key is pressed. * * @param inKey ASCII representation of the pressed key. * @param inX x position of mouse when key was pressed. * @param inY y position of mouse when key was pressed. */ virtual void keyPressed( unsigned char inKey, int inX, int inY ) = 0; /** * Callback function for when an ASCII-representable key is released. * * @param inKey ASCII representation of the released key. * @param inX x position of mouse when key was released. * @param inY y position of mouse when key was released. */ virtual void keyReleased( unsigned char inKey, int inX, int inY ) = 0; /** * Callback function for when an special key is pressed. * * @param inKey integer constant representation of the pressed key. * @param inX x position of mouse when key was pressed. * @param inY y position of mouse when key was pressed. */ virtual void specialKeyPressed( int inKey, int inX, int inY ) = 0; /** * Callback function for when an special key is released. * * @param inKey integer constant representation of the released key. * @param inX x position of mouse when key was released. * @param inY y position of mouse when key was released. */ virtual void specialKeyReleased( int inKey, int inX, int inY ) = 0; char mHandlerFlagged; protected: KeyboardHandlerGL() : mHandlerFlagged( false ) { } }; inline char KeyboardHandlerGL::isFocused() { return false; } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/testScreenGL.cpp0000640000175000017500000000113611435543334023241 0ustar pabspabs/* * Modification History * * 2000-December-19 Jason Rohrer * Created. * * 2001-February-2 Jason Rohrer * Fixed the random seed for testing. */ #include "TestHandlerGL.h" #include "ScreenGL.h" #include "minorGems/util/random/StdRandomSource.h" // simple test function int main() { StdRandomSource *randSource = new StdRandomSource( 2 ); TestHandlerGL *handler = new TestHandlerGL( randSource, 30 ); char *name = "test window"; ScreenGL *screen = new ScreenGL( 200, 200, false, name, handler, handler, handler ); handler->setupPrimitives(); screen->start(); } between-6+dfsg1.orig/minorGems/graphics/openGL/gui/0000750000175000017500000000000011435543334020755 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/graphics/openGL/gui/LabelGL.h0000640000175000017500000000566011435543334022400 0ustar pabspabs/* * Modification History * * 2001-October-13 Jason Rohrer * Created. * * 2001-October-29 Jason Rohrer * Added a missing destructor. * * 2006-December-19 Jason Rohrer * Made destructor virtual. * * 2008-October-1 Jason Rohrer * Added function for getting TextGL. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ #ifndef LABEL_GL_INCLUDED #define LABEL_GL_INCLUDED #include "GUIComponentGL.h" #include "TextGL.h" /** * A text label for OpenGL-based GUIs. * * @author Jason Rohrer */ class LabelGL : public GUIComponentGL { public: /** * Constructs a label. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. * @param inString the text to display in this label. * Is copied internally, so must be destroyed * by caller if not const. * @param inText the text object to use when drawing * this label. Must be destroyed by caller after * this class is destroyed. */ LabelGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, const char *inString, TextGL *inText ); virtual ~LabelGL(); /** * Sets the text displayed by this label. * * @param inString the text to display in this label. * Is copied internally, so must be destroyed * by caller if not const. */ void setText( const char *inString ); /** * Gets the text displayed by this label. * * @return the text to display in this label. * Must not be destroyed or modified by caller. */ char *getText(); /** * Gets the TextGL object used to draw this label. * * @return the TextGL object. * Must not be destroyed by caller until after this class is * destroyed. */ TextGL *getTextGL() { return mText; } // override fireRedraw in GUIComponentGL virtual void fireRedraw(); protected: TextGL *mText; char *mString; }; inline LabelGL::LabelGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, const char *inString, TextGL *inText ) : GUIComponentGL( inAnchorX, inAnchorY, inWidth, inHeight ), mText( inText ), mString( NULL ) { setText( inString ); } inline LabelGL::~LabelGL() { if( mString != NULL ) { delete [] mString; } } inline void LabelGL::setText( const char *inString ) { if( mString != NULL ) { delete [] mString; } int length = strlen( inString ) + 1; mString = new char[ length ]; memcpy( mString, inString, length ); } inline char *LabelGL::getText() { return mString; } inline void LabelGL::fireRedraw() { mText->drawText( mString, mAnchorX, mAnchorY, mWidth, mHeight ); } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/gui/GUIComponentGL.h0000640000175000017500000001551711435543334023672 0ustar pabspabs/* * Modification History * * 2001-September-15 Jason Rohrer * Created. * Changed to use normalized floating point coordinates. * Fixed some compile bugs. * Changed to extend the GUIComponent class. * * 2001-October-29 Jason Rohrer * Added support for focus. * * 2006-July-4 Jason Rohrer * Added support for disabled components. * * 2008-October-1 Jason Rohrer * Added position changing and gettting functions. * * 2009-December-28 Jason Rohrer * Added support for locking focus. */ #ifndef GUI_COMPONENT_GL_INCLUDED #define GUI_COMPONENT_GL_INCLUDED #include "minorGems/graphics/openGL/RedrawListenerGL.h" #include "minorGems/ui/GUIComponent.h" // for key codes #include "minorGems/graphics/openGL/KeyboardHandlerGL.h" /** * A base class for all OpenGL GUI components. * * Note that all coordinates are specified in a normalized * [0,1.0] space, where the screen is spanned by this [0,1.0] range. * * @author Jason Rohrer */ class GUIComponentGL : public GUIComponent, public RedrawListenerGL { public: virtual ~GUIComponentGL(); /** * Sets the position of this component. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. */ void setPosition( double inAnchorX, double inAnchorY, double inWidth, double inHeight ); // functions for getting position double getAnchorX() { return mAnchorX; } double getAnchorY() { return mAnchorY; } double getWidth() { return mWidth; } double getHeight() { return mHeight; } /** * Sets the enabled state of this component. * * @param inEnabled true to enable, or false to disable. */ virtual void setEnabled( char inEnabled ); /** * Gets the enabled state of this component. * * @return true to enable, or false to disable. */ virtual char isEnabled(); /** * Tests whether a point is inside this component. * * @param inX the x value to check. * @param inY the y value to check. * * @return true iff the point is insided this component. */ virtual char isInside( double inX, double inY ); /** * Sets this component's focus status. * * Note that this component may ignore this function call * and configure its own focus (for example, some * components are never focused). * * The default implementation ignores this call * and is never focused. * * @param inFocus true iff this component should be focused. */ virtual void setFocus( char inFocus ); /** * Locks the focus onto this component so that it keeps it * despite mouse clicks that would cause it to lose focus. * * @param inFocusLocked true to lock focus onto this component. */ virtual void lockFocus( char inFocusLocked ); virtual char isFocusLocked(); // the implementations below do nothing, but they allow // subclasses to pick which input they care about (and which // functions they want to override) // implements a normalized (to [0,1.0] version // of a MouseHandlerGL-like interface virtual void mouseMoved( double inX, double inY ); virtual void mouseDragged( double inX, double inY ); virtual void mousePressed( double inX, double inY ); virtual void mouseReleased( double inX, double inY ); // implements a normalized (to [0,1.0] version // of a KeyboardHandlerGL-like interface virtual char isFocused(); virtual void keyPressed( unsigned char inKey, double inX, double inY ); virtual void specialKeyPressed( int inKey, double inX, double inY ); virtual void keyReleased( unsigned char inKey, double inX, double inY ); virtual void specialKeyReleased( int inKey, double inX, double inY ); // implements the RedrawListenerGL interface virtual void fireRedraw(); protected: /** * Constructs a component. * * Should only be called by subclass constructors. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. */ GUIComponentGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight ); double mAnchorX; double mAnchorY; double mWidth; double mHeight; char mEnabled; char mFocusLocked; }; inline GUIComponentGL::GUIComponentGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight ) : mAnchorX( inAnchorX ), mAnchorY( inAnchorY ), mWidth( inWidth ), mHeight( inHeight ), mEnabled( true ), mFocusLocked( false ) { } inline GUIComponentGL::~GUIComponentGL() { } inline void GUIComponentGL::setPosition( double inAnchorX, double inAnchorY, double inWidth, double inHeight ) { mAnchorX = inAnchorX; mAnchorY = inAnchorY; mWidth = inWidth; mHeight = inHeight; } inline void GUIComponentGL::setEnabled( char inEnabled ) { mEnabled = inEnabled; } inline char GUIComponentGL::isEnabled() { return mEnabled; } inline char GUIComponentGL::isInside( double inX, double inY ) { if( inX >= mAnchorX && inX < mAnchorX + mWidth && inY >= mAnchorY && inY < mAnchorY + mHeight ) { return true; } else { return false; } } inline void GUIComponentGL::mouseMoved( double inX, double inY ) { } inline void GUIComponentGL::mouseDragged( double inX, double inY ) { } inline void GUIComponentGL::mousePressed( double inX, double inY ) { } inline void GUIComponentGL::mouseReleased( double inX, double inY ) { } inline void GUIComponentGL::setFocus( char inFocus ) { // default implementation ignores this call } inline void GUIComponentGL::lockFocus( char inFocusLocked ) { mFocusLocked = inFocusLocked; } inline char GUIComponentGL::isFocusLocked() { return mFocusLocked; } inline char GUIComponentGL::isFocused() { return false; } inline void GUIComponentGL::keyPressed( unsigned char inKey, double inX, double inY ) { } inline void GUIComponentGL::specialKeyPressed( int inKey, double inX, double inY ) { } inline void GUIComponentGL::keyReleased( unsigned char inKey, double inX, double inY ) { } inline void GUIComponentGL::specialKeyReleased( int inKey, double inX, double inY ) { } inline void GUIComponentGL::fireRedraw() { } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/gui/GUIPanelGL.h0000640000175000017500000000371711435543334022766 0ustar pabspabs/* * Modification History * * 2001-September-15 Jason Rohrer * Created. * * 2006-July-3 Jason Rohrer * Fixed warnings. * * 2006-September-8 Jason Rohrer * Made alpha-aware. */ #ifndef GUI_PANEL_GL_INCLUDED #define GUI_PANEL_GL_INCLUDED #include "GUIComponentGL.h" #include "GUIContainerGL.h" #include "minorGems/util/SimpleVector.h" #include "minorGems/graphics/Color.h" #include /** * A container with a background color that is drawn * behind the components. * * @author Jason Rohrer */ class GUIPanelGL : public GUIContainerGL { public: /** * Constructs a panel. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. * @param inColor the background color for this panel. * Will be destroyed when this class is destroyed. */ GUIPanelGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, Color *inColor ); virtual ~GUIPanelGL(); // override fireRedraw() in GUIComponentGL virtual void fireRedraw(); protected: Color *mColor; }; inline GUIPanelGL::GUIPanelGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, Color *inColor ) : GUIContainerGL( inAnchorX, inAnchorY, inWidth, inHeight ), mColor( inColor ) { } inline GUIPanelGL::~GUIPanelGL() { delete mColor; } inline void GUIPanelGL::fireRedraw() { // draw our background color as a rectangle glColor4f( mColor->r, mColor->g, mColor->b, mColor->a ); glBegin( GL_QUADS ); { glVertex2d( mAnchorX, mAnchorY ); glVertex2d( mAnchorX + mWidth, mAnchorY ); glVertex2d( mAnchorX + mWidth, mAnchorY + mHeight ); glVertex2d( mAnchorX, mAnchorY + mHeight ); } glEnd(); // call the supercalss redraw GUIContainerGL::fireRedraw(); } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/gui/ImageButtonGL.h0000640000175000017500000000647311435543334023602 0ustar pabspabs/* * Modification History * * 2006-July-3 Jason Rohrer * Created. * * 2007-March-17 Jason Rohrer * Enabled blending (why was it off?) * * 2010-March-31 Jason Rohrer * Changed glColor3f to 4f to fix driver bug on some video cards. */ #ifndef IMAGE_BUTTON_GL_INCLUDED #define IMAGE_BUTTON_GL_INCLUDED #include "ButtonGL.h" #include "minorGems/graphics/Image.h" #include "minorGems/graphics/openGL/SingleTextureGL.h" #include /** * A textured button for GL-based GUIs. * * @author Jason Rohrer */ class ImageButtonGL : public ButtonGL { public: /** * Constructs a button. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. * @param inUnpressedImage the image to display * when this button is unpressed. Must have dimensions * that are powers of 2. * Will be destroyed when this class is destroyed. * @param inPressedImage the image to display * when this button is pressed. Must have dimensions * that are powers of 2. * Will be destroyed when this class is destroyed. */ ImageButtonGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, Image *inUnpressedImage, Image *inPressedImage ); ~ImageButtonGL(); // implements the ButtonGL interface virtual void drawPressed(); virtual void drawUnpressed(); protected: Image *mUnpressedImage; Image *mPressedImage; SingleTextureGL *mUnpressedTexture; SingleTextureGL *mPressedTexture; SingleTextureGL *mCurrentTexture; /** * Draw this button using a specific texture. * * @param inTexture the texture. * Destroyed by caller. */ void drawWithTexture( SingleTextureGL *inTexture ); }; inline ImageButtonGL::ImageButtonGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, Image *inUnpressedImage, Image *inPressedImage ) : ButtonGL( inAnchorX, inAnchorY, inWidth, inHeight ), mUnpressedImage( inUnpressedImage ), mPressedImage( inPressedImage ) { mUnpressedTexture = new SingleTextureGL( mUnpressedImage ); mPressedTexture = new SingleTextureGL( mPressedImage ); mCurrentTexture = mUnpressedTexture; } inline ImageButtonGL::~ImageButtonGL() { delete mUnpressedImage; delete mPressedImage; delete mUnpressedTexture; delete mPressedTexture; } inline void ImageButtonGL::drawPressed() { drawWithTexture( mPressedTexture ); } inline void ImageButtonGL::drawUnpressed() { drawWithTexture( mUnpressedTexture ); } inline void ImageButtonGL::drawWithTexture( SingleTextureGL *inTexture ) { // set our texture inTexture->enable(); glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); //glDisable( GL_BLEND ); glBegin( GL_QUADS ); { glTexCoord2f( 0, 1.0f ); glVertex2d( mAnchorX, mAnchorY ); glTexCoord2f( 1.0f, 1.0f ); glVertex2d( mAnchorX + mWidth, mAnchorY ); glTexCoord2f( 1.0f, 0 ); glVertex2d( mAnchorX + mWidth, mAnchorY + mHeight ); glTexCoord2f( 0, 0 ); glVertex2d( mAnchorX, mAnchorY + mHeight ); } glEnd(); inTexture->disable(); } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/gui/GUIContainerGL.h0000640000175000017500000002262711435543334023652 0ustar pabspabs/* * Modification History * * 2001-September-15 Jason Rohrer * Created. * Changed to use normalized floating point coordinates. * Fixed some compile bugs. * Changed so that mouse released events are passed to all components. * * 2001-October-29 Jason Rohrer * Added support for focus, including mouse-release to focus. * * 2001-November-2 Jason Rohrer * Changed to send keyboard events only to focused components, * regardless of mouse position. * * 2006-July-3 Jason Rohrer * Fixed warnings. * * 2006-September-8 Jason Rohrer * Switched to passing mouse motion events to all components. * * 2006-December-14 Jason Rohrer * Added function for testing containment. * * 2009-December-22 Jason Rohrer * New SimpleVector delete call. * * 2009-December-28 Jason Rohrer * Added support for locking focus. * * 2010-April-8 Jason Rohrer * Fixed focus behavior for presses that didn't start on a component. * Only pass focus to enabled components. * * 2010-April-9 Jason Rohrer * Fixed crash when components removed by a mouse event. */ #ifndef GUI_CONTAINER_GL_INCLUDED #define GUI_CONTAINER_GL_INCLUDED #include "GUIComponentGL.h" #include "minorGems/util/SimpleVector.h" /** * A container full of gui components that delegates * redraw and ui events to the contained components. * * @author Jason Rohrer */ class GUIContainerGL : public GUIComponentGL { public: /** * Constructs a container. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. */ GUIContainerGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight ); virtual ~GUIContainerGL(); /** * Adds a component to this container. * * Note that the added component should lie within the bounds * of this container (or else event delegation may not function * properly). * * @param inComponent the component to add. Is destroyed * when this container is destroyed. */ virtual void add( GUIComponentGL *inComponent ); /** * Removes a component from this container. * * @param inComponent the component to remove. Must be * destroyed by the caller. * * @return true iff the component was removed successfully. */ virtual char remove( GUIComponentGL *inComponent ); /** * Gets whether this container contains a given component. * * @param inComponent the component to look for. * * @return true if inComponent is in this container. */ virtual char contains( GUIComponentGL *inComponent ); // the implementations below delegate events to appropriate // contained components // override functions in GUIComponentGL virtual void mouseMoved( double inX, double inY ); virtual void mouseDragged( double inX, double inY ); virtual void mousePressed( double inX, double inY ); virtual void mouseReleased( double inX, double inY ); virtual char isFocused(); virtual void keyPressed( unsigned char inKey, double inX, double inY ); virtual void specialKeyPressed( int inKey, double inX, double inY ); virtual void keyReleased( unsigned char inKey, double inX, double inY ); virtual void specialKeyReleased( int inKey, double inX, double inY ); virtual void fireRedraw(); protected: SimpleVector *mComponentVector; // flags to track components in which a press started SimpleVector *mPressStartedHereVector; }; inline GUIContainerGL::GUIContainerGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight ) : GUIComponentGL( inAnchorX, inAnchorY, inWidth, inHeight ), mComponentVector( new SimpleVector() ), mPressStartedHereVector( new SimpleVector() ) { } inline GUIContainerGL::~GUIContainerGL() { // delete each contained component for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); delete component; } delete mComponentVector; delete mPressStartedHereVector; } inline void GUIContainerGL::add( GUIComponentGL *inComponent ) { mComponentVector->push_back( inComponent ); mPressStartedHereVector->push_back( false ); } inline char GUIContainerGL::remove( GUIComponentGL *inComponent ) { int index = mComponentVector->getElementIndex( inComponent ); if( index != -1 ) { mComponentVector->deleteElement( index ); mPressStartedHereVector->deleteElement( index ); return true; } return false; } inline char GUIContainerGL::contains( GUIComponentGL *inComponent ) { int index = mComponentVector->getElementIndex( inComponent ); if( index >= 0 ) { return true; } else { return false; } } inline void GUIContainerGL::mouseMoved( double inX, double inY ) { for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); component->mouseMoved( inX, inY ); } } inline void GUIContainerGL::mouseDragged( double inX, double inY ) { // released events should be passed to all components // so that a pressed component can react if the mouse // is dragged elsewhere for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); component->mouseDragged( inX, inY ); } } inline void GUIContainerGL::mousePressed( double inX, double inY ) { // only pass pressed events to components // that contain the coordinate pressed for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); if( component->isInside( inX, inY ) ) { component->mousePressed( inX, inY ); // components MIGHT get removed by the event call, thus, our // vector might be too short for i now if( i < mComponentVector->size() ) { *( mPressStartedHereVector->getElement( i ) ) = true; } } else { // press started elsewhere *( mPressStartedHereVector->getElement( i ) ) = false; } } } inline void GUIContainerGL::mouseReleased( double inX, double inY ) { // first, unfocus all components, but skip those that are locked for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); if( !component->isFocusLocked() ) { component->setFocus( false ); } } // released events should be passed to all components // so that a pressed component can react if the mouse // is released elsewhere for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); component->mouseReleased( inX, inY ); // components MIGHT get removed by the event call, thus, our // vector might be too short for i now if( i < mComponentVector->size() ) { // focus any components hit by the release directly // IF press started there if( component->isInside( inX, inY ) && component->isEnabled() && *( mPressStartedHereVector->getElement(i) ) ) { component->setFocus( true ); } } } } inline char GUIContainerGL::isFocused() { // we are focused if any of our sub-components are focused for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); if( component->isFocused() ) { return true; } } // else, none focused return false; } inline void GUIContainerGL::keyPressed( unsigned char inKey, double inX, double inY ) { for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); // only send events to focused components if( component->isFocused() ) { component->keyPressed( inKey, inX, inY ); } } } inline void GUIContainerGL::specialKeyPressed( int inKey, double inX, double inY ) { for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); // only send events to focused components if( component->isFocused() ) { component->specialKeyPressed( inKey, inX, inY ); } } } inline void GUIContainerGL::keyReleased( unsigned char inKey, double inX, double inY ) { for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); // only send events to focused components if( component->isFocused() ) { component->keyReleased( inKey, inX, inY ); } } } inline void GUIContainerGL::specialKeyReleased( int inKey, double inX, double inY ) { for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); // only send events to focused components if( component->isFocused() ) { component->specialKeyReleased( inKey, inX, inY ); } } } inline void GUIContainerGL::fireRedraw() { for( int i=0; isize(); i++ ) { GUIComponentGL *component = *( mComponentVector->getElement( i ) ); component->fireRedraw(); } } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/gui/MultiButtonGL.h0000640000175000017500000001603711435543334023647 0ustar pabspabs/* * Modification History * * 2001-September-16 Jason Rohrer * Created. * * 2001-November-3 Jason Rohrer * Fixed a gutter size bug that occurred when there was * only one row or column. * Changed so that rows are filled before adding new columns. * Fixed a bug in setSelectedIndex. */ #ifndef MULTI_BUTTON_GL_INCLUDED #define MULTI_BUTTON_GL_INCLUDED #include "GUIContainerGL.h" #include "StickyButtonGL.h" #include "minorGems/graphics/Image.h" #include "minorGems/ui/event/ActionListenerList.h" #include "minorGems/ui/event/ActionListener.h" #include "minorGems/ui/GUIComponent.h" #include #include /** * A set of buttons that allows only one to be depressed * at a time. * * @author Jason Rohrer */ class MultiButtonGL : public GUIContainerGL, public ActionListener, public ActionListenerList { public: /** * Constructs a set of buttons. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. * @param inNumButtons the number of buttons in the set. * @param inUnpressedImages the images to display * when each button is unpressed. Images must have dimensions * that are powers of 2. * Will be destroyed when this class is destroyed. * @param inPressedImages the images to display * when each button is pressed. Images must have dimensions * that are powers of 2. * Will be destroyed when this class is destroyed. * @param inGutterFraction the fraction of each row * and column that should be taken up by the gutters * (the spaces between buttons). In [0, 1.0]. */ MultiButtonGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, int inNumButtons, Image **inUnpressedImages, Image **inPressedImages, double inGutterFraction ); ~MultiButtonGL(); /** * Sets the currently depressed button. * * Note that if this function causes a change * in the state of the set, an action will * be fired to all registered listeners. * * @param inButtonIndex the index of the button to depress. */ void setSelectedButton( int inButtonIndex ); /** * Gets the index of the currently depressed button. * * Note that if this function causes a change * in the state of the set, an action will * be fired to all registered listeners. * * @return the index of the button that is depressed. */ int getSelectedButton(); // we don't need to override any mouse // or redraw functions, since the container // and the buttons should handle these correctly // implements the ActionListener interface virtual void actionPerformed( GUIComponent *inTarget ); protected: int mNumButtons; StickyButtonGL **mButtons; int mSelectedIndex; char mIgnoreEvents; /** * Maps a button in mButtons to its index in the * mButtons array. * * @param inButton the button to get an index for. * * @return the index of inButton in the mButtons array. */ int buttonToIndex( StickyButtonGL *inButton ); }; inline MultiButtonGL::MultiButtonGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, int inNumButtons, Image **inUnpressedImages, Image **inPressedImages, double inGutterFraction ) : GUIContainerGL( inAnchorX, inAnchorY, inWidth, inHeight ), mNumButtons( inNumButtons ), mButtons( new StickyButtonGL*[inNumButtons] ), mSelectedIndex( 0 ), mIgnoreEvents( false ) { int numColumns = (int)( sqrt( mNumButtons ) ); int numRows = mNumButtons / numColumns; while( numRows * numColumns < mNumButtons ) { numRows++; } // determine gutter and button sizes double gutterSizeX; double gutterSizeY; if( numRows == 1 ) { gutterSizeY = 0; } else { gutterSizeY = ( inHeight * inGutterFraction ) / ( numRows - 1 ); } if( numColumns == 1 ) { gutterSizeX = 0; } else { gutterSizeX = ( inWidth * inGutterFraction ) / ( numColumns - 1 ); } double buttonSizeX = ( inWidth * ( 1 - inGutterFraction ) ) / ( numColumns ); double buttonSizeY = ( inHeight * ( 1 - inGutterFraction ) ) / ( numRows ); // setup each button int buttonIndex = 0; for( int r=0; r= mNumButtons ) { // jump out of our loop if we run out of buttons c = numColumns; r = numRows; } } } // now we've added all of our buttons // press one of them before we add any listeners mButtons[ mSelectedIndex ]->setPressed( true ); // now add ourselves as an action listener to each button for( int i=0; iaddActionListener( this ); } // delete the arrays pointing to the images, since // they are no longer needed delete [] inUnpressedImages; delete [] inPressedImages; } inline MultiButtonGL::~MultiButtonGL() { // note that we don't need to delete the buttons // themselves, since they will be deleted by GUIContainer // destructor delete [] mButtons; } inline void MultiButtonGL::setSelectedButton( int inButtonIndex ) { // simply press the appropriate button, and let the // action handlers do the rest mButtons[ inButtonIndex ]->setPressed( true ); } inline int MultiButtonGL::getSelectedButton() { return mSelectedIndex; } inline void MultiButtonGL::actionPerformed( GUIComponent *inTarget ) { if( !mIgnoreEvents ) { int buttonIndex = buttonToIndex( (StickyButtonGL*)inTarget ); // if another button is being pressed if( buttonIndex != mSelectedIndex && mButtons[ buttonIndex ]->isPressed() ) { // unpress the old button, ignoring the resulting event mIgnoreEvents = true; mButtons[ mSelectedIndex ]->setPressed( false ); mIgnoreEvents = false; mSelectedIndex = buttonIndex; fireActionPerformed( this ); } // else if our selected button is being unpressed else if( buttonIndex == mSelectedIndex && !( mButtons[ buttonIndex ]->isPressed() ) ) { // don't allow it to become unpressed // re-press it, ignoring the resulting event mIgnoreEvents = true; mButtons[ mSelectedIndex ]->setPressed( true ); mIgnoreEvents = false; // don't fire an action, since our state // has not changed } } } inline int MultiButtonGL::buttonToIndex( StickyButtonGL *inButton ) { for( int i=0; i /** * A textured button for GL-based GUIs that draws one image with a shadow * to show pressed/unpressed status. * * @author Jason Rohrer */ class ShadowImageButtonGL : public ButtonGL { public: /** * Constructs a button. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. * @param inUnpressedImage the image to display * when this button is unpressed. Must have dimensions * that are powers of 2. * Will be destroyed when this class is destroyed. */ ShadowImageButtonGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, Image *inUnpressedImage ); ~ShadowImageButtonGL(); // implements the ButtonGL interface virtual void drawPressed(); virtual void drawUnpressed(); protected: Image *mUnpressedImage; SingleTextureGL *mUnpressedTexture; /** * Draw this button with an optional z offset above it's shadow. * * @param inOffset true to draw the button above its shadow. */ void drawWithOffset( char inOffset ); }; inline ShadowImageButtonGL::ShadowImageButtonGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, Image *inUnpressedImage ) : ButtonGL( inAnchorX, inAnchorY, inWidth, inHeight ), mUnpressedImage( inUnpressedImage ) { mUnpressedTexture = new SingleTextureGL( mUnpressedImage ); } inline ShadowImageButtonGL::~ShadowImageButtonGL() { delete mUnpressedImage; delete mUnpressedTexture; } inline void ShadowImageButtonGL::drawPressed() { drawWithOffset( false ); } inline void ShadowImageButtonGL::drawUnpressed() { drawWithOffset( true ); } inline void ShadowImageButtonGL::drawWithOffset( char inOffset ) { // calculate offset for shadow double xOffset = mWidth * 0.05; double yOffset = mHeight * 0.05; // use smaller double offset = xOffset; if( yOffset < xOffset ) { offset = yOffset; } // set our texture mUnpressedTexture->enable(); // shadow first glColor4f( 0.0, 0.0, 0.0, 0.5 ); // shadow in lower left corner glBegin( GL_QUADS ); { glTexCoord2f( 0, 1.0f ); glVertex2d( mAnchorX, mAnchorY ); glTexCoord2f( 1.0f, 1.0f ); glVertex2d( mAnchorX + mWidth - offset, mAnchorY ); glTexCoord2f( 1.0f, 0 ); glVertex2d( mAnchorX + mWidth - offset, mAnchorY + mHeight - offset ); glTexCoord2f( 0, 0 ); glVertex2d( mAnchorX, mAnchorY + mHeight - offset ); } glEnd(); // now button image glColor4f( 1.0, 1.0, 1.0, 10 ); double anchorOffset = 0; if( inOffset ) { // put it in upper right corner anchorOffset = offset; offset = 0; } glBegin( GL_QUADS ); { glTexCoord2f( 0, 1.0f ); glVertex2d( mAnchorX + anchorOffset, mAnchorY + anchorOffset ); glTexCoord2f( 1.0f, 1.0f ); glVertex2d( mAnchorX + mWidth - offset, mAnchorY + anchorOffset ); glTexCoord2f( 1.0f, 0 ); glVertex2d( mAnchorX + mWidth - offset, mAnchorY + mHeight - offset ); glTexCoord2f( 0, 0 ); glVertex2d( mAnchorX + anchorOffset, mAnchorY + mHeight - offset ); } glEnd(); mUnpressedTexture->disable(); } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/gui/TextFieldGL.h0000640000175000017500000003752111435543334023252 0ustar pabspabs/* * Modification History * * 2001-October-29 Jason Rohrer * Created. * * 2001-November-2 Jason Rohrer * Added support for cursor position. * Added support for clicking to reposition the cursor. * Fixed an array out-of-bounds bug in the keyReleased function. * * 2008-September-29 Jason Rohrer * Improved text width handling and cursor spacing. * Added length limit. * * 2008-October-27 Jason Rohrer * Switched to implementation-independent keycodes. * Switched to key press (instead of release) events. * * 2008-November-1 Jason Rohrer * Added support for forced upper case. * * 2009-December-29 Jason Rohrer * Added support for setting cursor position. * * 2010-January-1 Jason Rohrer * Does NOT fire event when text changed externally. * * 2010-January-11 Jason Rohrer * Fixed mouse-based cursor positioning. * * 2010-January-27 Jason Rohrer * Fixed bug in text editing. * * 2010-January-29 Jason Rohrer * Added parameter for border width. * * 2010-March-6 Jason Rohrer * Added support for ignoring one key-press. * * 2010-March-31 Jason Rohrer * Changed glColor3f to 4f to fix driver bug on some video cards. * * 2010-April-6 Jason Rohrer * Enlarged click area. * * 2010-April-8 Jason Rohrer * Fixed behavior for presses that didn't start on this field. * * 2010-May-7 Jason Rohrer * Extended ASCII. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. * * 2010-May-25 Jason Rohrer * Based border offset on border width (instead of 1/8 height). */ #ifndef TEXT_FIELD_GL_INCLUDED #define TEXT_FIELD_GL_INCLUDED #include "GUIComponentGL.h" #include "TextGL.h" #include "minorGems/graphics/Color.h" #include "minorGems/util/stringUtils.h" #include "minorGems/ui/event/ActionListenerList.h" /** * A text field for OpenGL-based GUIs. * Will fire an event to listeners every time text changes * * @author Jason Rohrer */ class TextFieldGL : public GUIComponentGL, public ActionListenerList { public: /** * Constructs a text field. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. * @param inBorderWidth width of the border and the cursor. * @param inString the text to display in this text field. * Is copied internally, so must be destroyed * by caller if not const. * @param inText the text object to use when drawing * this textField. Must be destroyed by caller after * this class is destroyed. * @param inBorderColor the color of this field's border. * Will be destroyed when this class is destroyed. * @param inFocusedBorderColor the color of this field's border * when the field is focused. * Will be destroyed when this class is destroyed. * @param inBackgroundColor the color of this field's background. * Will be destroyed when this class is destroyed. * @param inCursorColor the color of this field's cursor line. * Will be destroyed when this class is destroyed. * @param inLengthLimit the length limit for the entered string, * or -1 for no limit. Defaults to -1. * @param inForceUppercase true to force upper case for text entered. * Defaults to false. */ TextFieldGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, double inBorderWidth, const char *inString, TextGL *inText, Color *inBorderColor, Color *inFocusedBorderColor, Color *inBackgroundColor, Color *inCursorColor, int inLengthLimit = -1, char inForceUppercase = false ); ~TextFieldGL(); /** * Sets the text displayed by this text field. * * @param inString the text to display in this text field. * Is copied internally, so must be destroyed * by caller if not const. */ void setText( const char *inString ); /** * Gets the text displayed by this text field. * * @return the text to display in this textField. * Must not be destroyed or modified by caller. */ char *getText(); /** * Ignore next 1 key press. * * Useful for when this field becomes focused due to a key press * (like from a key-based menu selection) but we don't want that * key press passed immediately into the field. */ void ignoreNextKey(); void setCursorPosition( int inCharPosition ); // override functions in GUIComponentGL virtual void setFocus( char inFocus ); virtual char isFocused(); virtual void keyPressed( unsigned char inKey, double inX, double inY ); virtual void specialKeyPressed( int inKey, double inX, double inY ); virtual void keyReleased( unsigned char inKey, double inX, double inY ); virtual void specialKeyReleased( int inKey, double inX, double inY ); virtual void mousePressed( double inX, double inY ); virtual void mouseReleased( double inX, double inY ); virtual void fireRedraw(); // override this to make click area slightly bigger // (so it includes the border) virtual char isInside( double inX, double inY ); protected: /** * Adjusts the cursor position to bring it in bounds of the * current string. */ void fixCursorPosition(); TextGL *mText; char *mString; Color *mBorderColor; Color *mFocusedBorderColor; Color *mBackgroundColor; Color *mCursorColor; Color *mCurrentBorderColor; int mLengthLimit; char mForceUppercase; char mFocused; // cursor position, in number of characters int mCursorPosition; double mBorderWidth; char mIgnoreNextKey; char mPressStartedOnUs; }; inline TextFieldGL::TextFieldGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, double inBorderWidth, const char *inString, TextGL *inText, Color *inBorderColor, Color *inFocusedBorderColor, Color *inBackgroundColor, Color *inCursorColor, int inLengthLimit, char inForceUppercase ) : GUIComponentGL( inAnchorX, inAnchorY, inWidth, inHeight ), mText( inText ), mString( NULL ), mBorderColor( inBorderColor ), mFocusedBorderColor( inFocusedBorderColor ), mBackgroundColor( inBackgroundColor ), mCursorColor( inCursorColor ), mCurrentBorderColor( inBorderColor ), mLengthLimit( inLengthLimit ), mForceUppercase( inForceUppercase ), mFocused( false ), mCursorPosition( 0 ), mBorderWidth( inBorderWidth ), mIgnoreNextKey( false ), mPressStartedOnUs( false ) { setText( inString ); } inline TextFieldGL::~TextFieldGL() { if( mString != NULL ) { delete [] mString; } delete mBorderColor; delete mFocusedBorderColor; delete mBackgroundColor; delete mCursorColor; } inline void TextFieldGL::setText( const char *inString ) { if( mString != NULL ) { delete [] mString; } int length = strlen( inString ) + 1; mString = new char[ length ]; memcpy( mString, inString, length ); } inline char *TextFieldGL::getText() { return mString; } inline void TextFieldGL::ignoreNextKey() { mIgnoreNextKey = true; } inline void TextFieldGL::setCursorPosition( int inCharPosition ) { int maxPosition = strlen( mString ); if( inCharPosition > maxPosition ) { inCharPosition = maxPosition; } mCursorPosition = inCharPosition; } inline void TextFieldGL::setFocus( char inFocus ) { mFocused = inFocus; if( mFocused ) { mCurrentBorderColor = mFocusedBorderColor; } else { mCurrentBorderColor = mBorderColor; } } inline char TextFieldGL::isFocused() { return mFocused; } inline void TextFieldGL::keyPressed( unsigned char inKey, double inX, double inY ) { if( mIgnoreNextKey ) { mIgnoreNextKey = false; return; } //printf( "key press: %d\n", inKey ); // backspace and delete if( inKey == 127 || inKey == 8 ) { if( mCursorPosition != 0 ) { int length = strlen( mString ); if( length != 0 ) { char *newString = new char[ length ]; // copy mString up to the last char before the deleted char memcpy( newString, mString, mCursorPosition-1 ); // copy the portion of mString after the deleted char // this will include the trailing \0 memcpy( &( newString[mCursorPosition-1] ), &( mString[mCursorPosition] ), length - mCursorPosition + 1 ); setText( newString ); delete [] newString; mCursorPosition--; fireActionPerformed( this ); } } } // allowable character key, from space up to tilde, then extended ascii // ignore after length limit reached else if( ( (inKey >= 32 && inKey <= 126) || (inKey >= 160 ) ) && ( mLengthLimit < 0 || (int)strlen( mString ) < mLengthLimit ) ) { // add a character to our string int oldStringLength = strlen( mString ); int length = oldStringLength + 2; char *newString = new char[ length ]; if( mCursorPosition != 0 ) { // copy chars up to cursor position memcpy( newString, mString, mCursorPosition ); } // copy chars after cursor position, including trailing \0 memcpy( &( newString[mCursorPosition+1] ), &( mString[mCursorPosition] ), oldStringLength - mCursorPosition + 1 ); if( mForceUppercase ) { inKey = toupper( inKey ); } // now stick in the inserted char newString[ mCursorPosition ] = inKey; setText( newString ); delete [] newString; mCursorPosition++; fireActionPerformed( this ); } // else a non-valid key hit } inline void TextFieldGL::specialKeyPressed( int inKey, double inX, double inY ) { if( mIgnoreNextKey ) { mIgnoreNextKey = false; return; } switch( inKey ) { case MG_KEY_RIGHT: mCursorPosition++; break; case MG_KEY_LEFT: mCursorPosition--; default: break; } fixCursorPosition(); } inline void TextFieldGL::keyReleased( unsigned char inKey, double inX, double inY ) { } inline void TextFieldGL::specialKeyReleased( int inKey, double inX, double inY ) { } inline char TextFieldGL::isInside( double inX, double inY ) { // offset to give text room double offset = mBorderWidth;//mHeight * 0.125; // draw border quad behind background double borderOffset = offset + mBorderWidth; if( inX >= mAnchorX - borderOffset && inX < mAnchorX + mWidth + borderOffset && inY >= mAnchorY - borderOffset && inY < mAnchorY + mHeight + borderOffset ) { return true; } else { return false; } } inline void TextFieldGL::mousePressed( double inX, double inY ) { if( isEnabled() ) { // we'll only get pressed events if the mouse is pressed on us // so we don't need to check isInside status mPressStartedOnUs = true; } } inline void TextFieldGL::mouseReleased( double inX, double inY ) { if( isInside( inX, inY ) && mPressStartedOnUs ) { double offset = mHeight * 0.1; int numChars = strlen( mString ); // measure longer substrings until we find place where mouse clicked char found = false; for( int i=0; imeasureTextWidth( substring ) * mHeight + offset; if( i < numChars ) { // if click is halfway into next char, put cursor before // next char char nextChar[2] = { mString[i], '\0' }; subWidth += mText->measureTextWidth( nextChar ) * mHeight * 0.5; } delete [] substring; if( subWidth > inX - mAnchorX ) { mCursorPosition = i; found = true; } } if( !found ) { // stick cursor at very end mCursorPosition = numChars; } /* mCursorPosition = (int)( 0.5 + strlen( mString ) * ( inX - mAnchorX ) / mWidth ); */ } // reset for next time mPressStartedOnUs = false; } inline void TextFieldGL::fixCursorPosition() { if( mCursorPosition < 0 ) { mCursorPosition = 0; } else { int stringLength = strlen( mString ); if( mCursorPosition > stringLength ) { mCursorPosition = stringLength; } } } inline void TextFieldGL::fireRedraw() { // offset to give text room double offset = mBorderWidth;//mHeight * 0.125; // draw border quad behind background double borderOffset = offset + mBorderWidth; glColor4f( mCurrentBorderColor->r, mCurrentBorderColor->g, mCurrentBorderColor->b, 1.0f ); glBegin( GL_QUADS ); { glVertex2d( mAnchorX - borderOffset, mAnchorY - borderOffset ); glVertex2d( mAnchorX - borderOffset, mAnchorY + mHeight + borderOffset ); glVertex2d( mAnchorX + mWidth + borderOffset, mAnchorY + mHeight + borderOffset ); glVertex2d( mAnchorX + mWidth + borderOffset, mAnchorY - borderOffset ); } glEnd(); // draw the background glColor4f( mBackgroundColor->r, mBackgroundColor->g, mBackgroundColor->b, 1.0f ); glBegin( GL_QUADS ); { glVertex2d( mAnchorX - offset, mAnchorY - offset ); glVertex2d( mAnchorX - offset, mAnchorY + mHeight + offset ); glVertex2d( mAnchorX + mWidth + offset, mAnchorY + mHeight + offset ); glVertex2d( mAnchorX + mWidth + offset, mAnchorY - offset ); } glEnd(); double charWidth = mHeight * strlen( mString ); // draw the text mText->drawText( mString, mAnchorX, mAnchorY, charWidth, mHeight ); if( mFocused ) { // draw the cursor glColor4f( mCursorColor->r, mCursorColor->g, mCursorColor->b, 1.0f ); /* glBegin( GL_LINES ); { // make a temp sub-string and measure its length char *substring = stringDuplicate( mString ); substring[ mCursorPosition ] = '\0'; double subWidth = mText->measureTextWidth( substring ) * mHeight + offset; delete [] substring; double cursorViewX = mAnchorX + subWidth; glVertex2d( cursorViewX, mAnchorY ); glVertex2d( cursorViewX, mAnchorY + mHeight ); } glEnd(); */ // make a temp sub-string and measure its length char *substring = stringDuplicate( mString ); substring[ mCursorPosition ] = '\0'; double subWidth = mText->measureTextWidth( substring ) * mHeight ;//+ offset; delete [] substring; double cursorViewX = mAnchorX + subWidth; double cursorOffset = mBorderWidth / 2; glBegin( GL_QUADS ); { glVertex2d( cursorViewX - cursorOffset, mAnchorY ); glVertex2d( cursorViewX - cursorOffset, mAnchorY + mHeight ); glVertex2d( cursorViewX + cursorOffset, mAnchorY + mHeight ); glVertex2d( cursorViewX + cursorOffset, mAnchorY ); } glEnd(); } /* // draw the border on top of the text and cursor glColor4f( mCurrentBorderColor->r, mCurrentBorderColor->g, mCurrentBorderColor->b, 1.0f ); glBegin( GL_LINE_LOOP ); { glVertex2d( mAnchorX - offset, mAnchorY - offset ); glVertex2d( mAnchorX - offset, mAnchorY + mHeight + offset ); glVertex2d( mAnchorX + mWidth + offset, mAnchorY + mHeight + offset ); glVertex2d( mAnchorX + mWidth + offset, mAnchorY - offset ); } glEnd(); */ } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/gui/SliderGL.h0000640000175000017500000002646011435543334022604 0ustar pabspabs/* * Modification History * * 2001-September-17 Jason Rohrer * Created. * * 2001-September-21 Jason Rohrer * Fixed a bug in thumb positioning in response to mouse position. * * 2001-September-23 Jason Rohrer * Fixed a bug in icon color clearing. * * 2009-December-25 Jason Rohrer * Added control over border/thumb width and thumb increments to fix rounding * errors. * * 2010-January-30 Jason Rohrer * Improved response when clicking. * * 2010-February-8 Jason Rohrer * Distinguish between first press and subsequent dragging. * * 2010-March-31 Jason Rohrer * Changed glColor3f to 4f to fix driver bug on some video cards. * * 2010-April-2 Jason Rohrer * Added functions for setting bar colors after construction. * * 2010-April-15 Jason Rohrer * Distinguish release event. */ #ifndef SLIDER_GL_INCLUDED #define SLIDER_GL_INCLUDED #include "GUIComponentGL.h" #include "minorGems/graphics/Image.h" #include "minorGems/graphics/Color.h" #include "minorGems/graphics/openGL/SingleTextureGL.h" #include "minorGems/ui/event/ActionListenerList.h" #include /** * A textured slider for GL-based GUIs. * * @author Jason Rohrer */ class SliderGL : public GUIComponentGL, public ActionListenerList { public: /** * Constructs a slider. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. * @param inIconImage the image to display * to the left of this slider. Must have dimensions * that are powers of 2. * Will be destroyed when this class is destroyed. * If set to NULL, then no icon will be drawn. * @param inIconWidthFraction the fraction of the slider's * width that should be taken up by the icon. * @param inBarStartColor the color on the left end of * the slider bar. * Will be destroyed when this class is destroyed. * @param inBarEndColor the color on the right end of * the slider bar. * Will be destroyed when this class is destroyed. * @param inThumbColor the color of the slider thumb. * Will be destroyed when this class is destroyed. * @param inBorderColor the color of the slider border. * Will be destroyed when this class is destroyed. * @param inBorderWidth width of the border. * @param inThumbWidth width of the slider thumb. * @param inMinThumbIncrement the minimum increment * at which to draw the slider thumb. */ SliderGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, Image *inIconImage, double inIconWidthFraction, Color *inBarStartColor, Color *inBarEndColor, Color *inThumbColor, Color *inBorderColor, double inBorderWidth, double inThumbWidth, double inMinThumbIncrement ); ~SliderGL(); // both are destroyed by this class void setBarStartColor( Color *inColor ); void setBarEndColor( Color *inColor ); /** * Gets the position of the slider thumb. * * @return the thumb position, in [0,1.0]. */ double getThumbPosition(); /** * Sets the position of the slider thumb. * * Note that if the slider thumb position changes * as a result of this call, then an action * will be fired to all registered listeners. * * @param inPosition the thumb position, in [0,1.0]. */ void setThumbPosition( double inPosition ); // override funxtions in GUIComponentGL virtual void mouseDragged( double inX, double inY ); virtual void mousePressed( double inX, double inY ); virtual void mouseReleased( double inX, double inY ); virtual void fireRedraw(); // is set to true for action fired from first press on a slider // adjustment, false for subsequent dragging for same adjustment char mJustPressed; // is set to true for action fired from mouse release on slider // at end of dragging char mJustReleased; // true iff the slider is currently being dragged char mDragging; protected: // common call for press and drag virtual void mouseInput( double inX, double inY ); SingleTextureGL *mIconTexture; double mIconWidthFraction; Color *mBarStartColor; Color *mBarEndColor; Color *mThumbColor; Color *mBorderColor; double mThumbPosition; double mBorderWidth; double mThumbWidth; double mMinThumbIncrement; // gets thumb position rounded to nearest increment double getPeggedThumbPosition(); }; inline SliderGL::SliderGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, Image *inIconImage, double inIconWidthFraction, Color *inBarStartColor, Color *inBarEndColor, Color *inThumbColor, Color *inBorderColor, double inBorderWidth, double inThumbWidth, double inMinThumbIncrement ) : GUIComponentGL( inAnchorX, inAnchorY, inWidth, inHeight ), mJustPressed( false ), mJustReleased( false ), mDragging( false ), mIconWidthFraction( inIconWidthFraction ), mBarStartColor( inBarStartColor ), mBarEndColor( inBarEndColor ), mThumbColor( inThumbColor ), mBorderColor( inBorderColor ), mThumbPosition( 0.5 ), mBorderWidth( inBorderWidth ), mThumbWidth( inThumbWidth ), mMinThumbIncrement( inMinThumbIncrement ) { mThumbPosition = (int)( mThumbPosition / mMinThumbIncrement ) * mMinThumbIncrement; if( inIconImage != NULL ) { mIconTexture = new SingleTextureGL( inIconImage ); // the image is no longer needed delete inIconImage; } else { mIconTexture = NULL; } } inline SliderGL::~SliderGL() { if( mIconTexture != NULL ) { delete mIconTexture; } delete mBarStartColor; delete mBarEndColor; delete mThumbColor; delete mBorderColor; } inline void SliderGL::setBarStartColor( Color *inColor ) { delete mBarStartColor; mBarStartColor = inColor; } inline void SliderGL::setBarEndColor( Color *inColor ) { delete mBarEndColor; mBarEndColor = inColor; } inline double SliderGL::getThumbPosition() { return mThumbPosition; } inline void SliderGL::setThumbPosition( double inPosition ) { if( mThumbPosition != inPosition ) { mThumbPosition = inPosition; fireActionPerformed( this ); } } inline double SliderGL::getPeggedThumbPosition() { double barWidth = mWidth * ( 1 - mIconWidthFraction ); double thumbUsableBarWidth = barWidth - mThumbWidth; return (int)( mThumbPosition * thumbUsableBarWidth / mMinThumbIncrement ) * mMinThumbIncrement / thumbUsableBarWidth; } inline void SliderGL::mouseInput( double inX, double inY ) { if( mDragging ) { double barWidth = mWidth * ( 1 - mIconWidthFraction ); double iconEndX = mAnchorX + mWidth - barWidth; // we want the mouse centered over the thumb double thumbUsableBarWidth = barWidth - mThumbWidth; mThumbPosition = ( inX - ( iconEndX + 0.5 * mThumbWidth ) ) / thumbUsableBarWidth; if( mThumbPosition > 1 ) { mThumbPosition = 1; } else if( mThumbPosition < 0 ) { mThumbPosition = 0; } // fire to listeners fireActionPerformed( this ); } } inline void SliderGL::mouseDragged( double inX, double inY ) { mJustPressed = false; mJustReleased = false; mouseInput( inX, inY ); } inline void SliderGL::mousePressed( double inX, double inY ) { // presses passed to us only on direct hit // (use to filter mouse activity that starts outside us) mDragging = true; mJustPressed = true; mJustReleased = false; mouseInput( inX, inY ); } inline void SliderGL::mouseReleased( double inX, double inY ) { // always stop dragging on a release mJustReleased = true; // one last event mouseInput( inX, inY ); mJustPressed = false; mDragging = false; } inline void SliderGL::fireRedraw() { // these values will change below if there is an icon double barStartX = mAnchorX; double barWidth = mWidth; if( mIconTexture != NULL ){ // first, draw the icon // set our texture mIconTexture->enable(); double textureStartX = mAnchorX; double textureStartY = mAnchorY; double textureEndX = mAnchorX + mIconWidthFraction * mWidth; double textureEndY = mAnchorY + mHeight; glBegin( GL_QUADS ); { // make sure our color is set to white for our texture // (to avoid leftover colors) glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); glTexCoord2f( 0, 1.0f ); glVertex2d( textureStartX, textureStartY ); glTexCoord2f( 1.0f, 1.0f ); glVertex2d( textureEndX, textureStartY ); glTexCoord2f( 1.0f, 0 ); glVertex2d( textureEndX, textureEndY ); glTexCoord2f( 0, 0 ); glVertex2d( textureStartX, textureEndY ); } glEnd(); mIconTexture->disable(); barWidth = mWidth * ( 1 - mIconWidthFraction ); barStartX = textureEndX; } // end check for a non-NULL icon texture // now, draw the slider bar double barHeight = 0.5 * mHeight; // center the bar vertically double barStartY = mAnchorY + ( mHeight - barHeight ) * 0.5; // draw it's border rectangle underneath glColor4f( mBorderColor->r, mBorderColor->g, mBorderColor->b, 1.0f ); glBegin( GL_QUADS ); { glVertex2d( barStartX, barStartY ); glVertex2d( barStartX, barStartY + barHeight ); glVertex2d( barStartX + barWidth, barStartY + barHeight ); glVertex2d( barStartX + barWidth, barStartY ); } glEnd(); // draw its gradient-filled center, smaller glBegin( GL_QUADS ); { // start of bar glColor4f( mBarStartColor->r, mBarStartColor->g, mBarStartColor->b, 1.0f ); glVertex2d( barStartX + mBorderWidth, barStartY + mBorderWidth ); glVertex2d( barStartX + mBorderWidth, barStartY + barHeight - mBorderWidth ); // end of bar glColor4f( mBarEndColor->r, mBarEndColor->g, mBarEndColor->b, 1.0f ); glVertex2d( barStartX + barWidth - mBorderWidth, barStartY + barHeight - mBorderWidth ); glVertex2d( barStartX + barWidth - mBorderWidth, barStartY + mBorderWidth ); } glEnd(); // now draw the thumb // we don't want the thumb going off the ends of the bar double thumbUsableBarWidth = barWidth - mThumbWidth; // round to nearest increment double thumbDrawPosition = getPeggedThumbPosition(); double thumbStartX = thumbDrawPosition * thumbUsableBarWidth + barStartX; double thumbEndX = thumbStartX + mThumbWidth; // draw its border, underneath glColor4f( mBorderColor->r, mBorderColor->g, mBorderColor->b, 1.0f ); glBegin( GL_QUADS ); { glVertex2d( thumbStartX, mAnchorY ); glVertex2d( thumbStartX, mAnchorY + mHeight ); glVertex2d( thumbEndX, mAnchorY + mHeight ); glVertex2d( thumbEndX, mAnchorY ); } glEnd(); // draw fill, smaller glColor4f( mThumbColor->r, mThumbColor->g, mThumbColor->b, 1.0f ); glBegin( GL_QUADS ); { glVertex2d( thumbStartX + mBorderWidth, mAnchorY + mBorderWidth ); glVertex2d( thumbStartX + mBorderWidth, mAnchorY + mHeight - mBorderWidth ); glVertex2d( thumbEndX - mBorderWidth, mAnchorY + mHeight - mBorderWidth ); glVertex2d( thumbEndX - mBorderWidth, mAnchorY + mBorderWidth ); } glEnd(); } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/gui/TextGL.h0000640000175000017500000005175311435543334022311 0ustar pabspabs/* * Modification History * * 2001-October-13 Jason Rohrer * Created. * Changed to support alpha-blended fonts, even for 3-channel font textures. * Fixed a bug in the font coloring. * * 2001-November-3 Jason Rohrer * Fixed some missing includes. * * 2006-December-26 Jason Rohrer * Added support for variable-width characers. * * 2007-March-4 Jason Rohrer * Added support for character z coordinates. * * 2007-March-15 Jason Rohrer * Added support for pixelated characters. Fixed font spacing issue. * * 2008-September-29 Jason Rohrer * Added support for font images with non-power-of-2 dimensions. * * 2010-January-29 Jason Rohrer * Fixed text measurement. * * 2010-May-7 Jason Rohrer * Extended ASCII. * * 2010-May-12 Jason Rohrer * Function to measure text height for Extended ASCII accents. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ #ifndef TEXT_GL_INCLUDED #define TEXT_GL_INCLUDED #include #include #include #include #include "minorGems/graphics/Color.h" #include "minorGems/graphics/Image.h" #include "minorGems/graphics/openGL/SingleTextureGL.h" /** * A class for drawing text strings to an OpenGL context. * Fonts are texture maps. * * @author Jason Rohrer */ class TextGL { public: /** * Constructs a gl text object. * * Note that this function can only be called * after an OpenGL drawing context has been created. * * @param inImage the image to use as a font texture. * If image is not square and height is greater than width, * extra height in each character is assumed to be the accent region * where characters can extend above normal vertical space. * Should have dimensions that are a * power of 2. * If dimensions are not a power of 2, then class will compensate * by padding image. * Fonts in the image are assumed to be in row-major ASCII order, * with 16 characters per row. * Must be destroyed by caller. Can be destroyed as soon as * this constructor returns. * @param inUseAlpha true iff alpha blending should * be used when rendering the font textures. If alpha * blending is enabled and the image has only 3 channels, * only the red channel (channel 0) * of the image is used: it is interpreted as the alpha * channel for a white fontset. * @param inFixedWidth true iff font should be displayed in fixed * width mode. If false, a width will be measured for each * character from the alpha channel. If inUseAlpha is false, * the font is always fixed width. Defaults to true. * @param inCharacterSpacingFraction the extra width-fraction of * spacing around each character. A fraction of a full character * width. Space is added on *both* sides of character. * Defaults to 0.1 * @param inSpaceWidthFraction the fraction of a full character width * occupied by a space. Defaults to 1.0 (a full width). */ TextGL( Image *inImage, char inUseAlpha = false, char inFixedWidth = true, double inCharacterSpacingFraction = 0.1, double inSpaceWidthFraction = 1.0 ); virtual ~TextGL(); /** * Sets the main color of the font. * * If the gradient color is non-NULL, this color will be at the * top of the fonts. Otherwise, the entire extent * of the font will be this color. * * @param inColor the main color of the font. * Will be destroyed when this class is destroyed. */ void setFontColor( Color *inColor ); /** * Gets the main color of the font. * * If the gradient color is non-NULL, this color will be at the * top of the fonts. Otherwise, the entire extent * of the font will be this color. * * @return the main color of the font. * Will be destroyed when this class is destroyed. */ Color *getFontColor(); /** * Sets the gradient color of the font. * * If non-NULL, this color will be at the * bottom of the fonts. * * @param inColor the gradient color of the font, or * NULL to disable the gradient. * Will be destroyed when this class is destroyed. */ void setGradientColor( Color *inColor ); /** * Gets the gradient color of the font. * * If non-NULL, this color will be at the * bottom of the fonts. * * @return the gradient color of the font, or * NULL if disable gradient disabled. * Will be destroyed when this class is destroyed. */ Color *getGradientColor(); /** * Sets the z coordinate for font drawing. * * Defaults to 0. * * @param inZ the z coordinate. */ void setFontZ( double inZ ); /** * Sets smothing. * * @param inSmooth true to enable smoothing of font texture (linear * interpolation) or false to show pure texture pixels (nearest * neighbor). */ void setSmoothing( char inSmooth ); /** * Draws a text string into a specified region of the * context. Text is squeezed to fit into the region. * * Uses the currently active OpenGL projection settings. * * @param inString the \0-delimited string to draw. * Must be destroyed by caller if not const. * @param inX the x coordinate of the region's lower-left * corner. * @param inY the y coordinate of the region's lower-left * corner. * @param inWidth the width of the region. * @param inHeight the height of the region. */ void drawText( const char *inString, double inX, double inY, double inWidth, double inHeight ); /** * Measures the width of a string of text. * * @inString the string to measure. Destroyed by caller. * * @return the width of the display text in character height * units. A return value of 8.5 means the string would be as * wide as 8.5 characters are high (if the string was displayed * with a 1:1 aspect ratio). */ double measureTextWidth( const char *inString ); /** * Measures the height of a string of text * * @inString the string to measure. Destroyed by caller. * * @return the height of the display text in character height * units (basic block character height, equal to block character * width, without considering special * accent space). A return value of 1.5 means the string extends * above the basic block height by 0.5. * This is the true height that a call to drawText would use * (measureTextHeight * inHeight). */ double measureTextHeight( const char *inString ); protected: double mXImageFractionUsed; double mYImageFractionUsed; // height/width of used area of whole font texture double mHWRatio; Color *mFontColor; Color *mGradientColor; double mZ; char mSmooth; SingleTextureGL *mFontTexture; char mUseAlpha; double *mStartWidthFractionMetrics; double *mEndWidthFractionMetrics; double mCharacterSpacingFraction; double *mHeightFractionMetrics; /** * Draws a character into a specified region of the * context. The character is squeezed to fit into the region. * * Uses the currently active OpenGL projection settings. * * @param inCharacter the character to draw. Unsigned to support * extended ASCII. * @param inX the x coordinate of the region's lower-left * corner. * @param inY the y coordinate of the region's lower-left * corner. * @param inWidth the width of the region. * @param inHeight the height of the region. * Note that character accents may extend above inHeight. * @param outUsedWidth pointer to where the actual width used * by this character should be returned. */ void drawCharacter( unsigned char inCharacter, double inX, double inY, double inWidth, double inHeight, double *outUsedWidth ); /** * Generates internal character width metrics from a font image. * * @param inFontImage the font image. Destroyed by caller. * @param inFixedWidth, inSpaceWidthFraction, * inCharacterSpacingFractionsame as parameters for the TextGL * constructor. */ void generateCharacterWidths( Image *inFontImage, char inFixedWidth, double inCharacterSpacingFraction, double inSpaceWidthFraction ); }; inline TextGL::TextGL( Image *inImage, char inUseAlpha, char inFixedWidth, double inCharacterSpacingFraction, double inSpaceWidthFraction ) : mXImageFractionUsed( 1.0 ), mYImageFractionUsed( 1.0 ), mFontColor( new Color( 1.0f, 1.0f, 1.0f, 1.0f ) ), mGradientColor( NULL ), mZ( 0 ), mSmooth( false ), mUseAlpha( inUseAlpha ), mStartWidthFractionMetrics( new double[ 256 ] ), mEndWidthFractionMetrics( new double[ 256 ] ), mCharacterSpacingFraction( inCharacterSpacingFraction ), mHeightFractionMetrics( new double[ 256 ] ) { // pad image to next power of 2 in each dimension int w = inImage->getWidth(); int h = inImage->getHeight(); int paddedW = w; int paddedH = h; double log2w = log( w ) / log( 2 ); double log2h = log( h ) / log( 2 ); int next2PowerW = (int)( ceil( log2w ) ); int next2PowerH = (int)( ceil( log2h ) ); if( next2PowerW != log2w ) { paddedW = (int)( pow( 2, next2PowerW ) ); mXImageFractionUsed = (double)w / (double)paddedW; } if( next2PowerH != log2h ) { paddedH = (int)( pow( 2, next2PowerH ) ); mYImageFractionUsed = (double)h / (double)paddedH; } mHWRatio = h / (double)w; // pad the image int numChannels = inImage->getNumChannels(); Image paddedImage( paddedW, paddedH, numChannels, true ); for( int c=0; cgetChannel( c ); for( int y=0; ygetChannel(3), paddedImage.getChannel(0), numPixels * sizeof( double ) ); // set other channels to white for( int c=0; c<3; c++ ) { double *channel = fontImage->getChannel( c ); for( int p=0; penable(); if( mSmooth ) { glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); } else { glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); } glBegin( GL_QUADS ); { if( mGradientColor != NULL ) { glColor4f( mGradientColor->r, mGradientColor->g, mGradientColor->b, mGradientColor->a ); } else { glColor4f( mFontColor->r, mFontColor->g, mFontColor->b, mFontColor->a ); } glTexCoord2f( textureStartX, textureStartY ); glVertex3d( charStartX, charStartY, mZ ); glTexCoord2f( textureEndX, textureStartY ); glVertex3d( charEndX, charStartY, mZ ); glColor4f( mFontColor->r, mFontColor->g, mFontColor->b, mFontColor->a ); glTexCoord2f( textureEndX, textureEndY ); glVertex3d( charEndX, charEndY, mZ ); glTexCoord2f( textureStartX, textureEndY ); glVertex3d( charStartX, charEndY, mZ ); } glEnd(); mFontTexture->disable(); } inline void TextGL::generateCharacterWidths( Image *inFontImage, char inFixedWidth, double inCharacterSpacingFraction, double inSpaceWidthFraction ) { if( mUseAlpha && ! inFixedWidth ) { double *alphaChannel = inFontImage->getChannel( 3 ); int imageWidth = inFontImage->getWidth(); int imageHeight = inFontImage->getHeight(); int pixelsPerCharacterX = (int)( mXImageFractionUsed * imageWidth ) / 16; int pixelsPerCharacterY = (int)( mYImageFractionUsed * imageHeight ) / 16; // look at each row and column in texture image for( int r=0; r<16; r++ ) { int charStartY = pixelsPerCharacterY * r; int charEndY = charStartY + pixelsPerCharacterY; for( int c=0; c<16; c++ ) { int charStartX = pixelsPerCharacterX * c; int charEndX = charStartX + pixelsPerCharacterX; // by "ink", I mean part of the image that has a non-zero // alpha // we want to find how far this character stretches to the // left and right within it's fixed-width region int smallestXWithInk = charEndX; int largestXWithInk = charStartX; // also how high (but don't care about how low) // also note that y coordinates inverted. int smallestYWithInk = charEndY; for( int x=charStartX; x 0 ) { // hit some ink if( x < smallestXWithInk ) { smallestXWithInk = x; } if( x > largestXWithInk ) { largestXWithInk = x; } if( y < smallestYWithInk ) { smallestYWithInk = y; } } } } int i = r * 16 + c; if( smallestXWithInk <= largestXWithInk ) { mStartWidthFractionMetrics[ i ] = (double)( smallestXWithInk - charStartX ) / (double)pixelsPerCharacterX; mEndWidthFractionMetrics[ i ] = (double)( largestXWithInk - charStartX ) / (double)pixelsPerCharacterX; mStartWidthFractionMetrics[ i ] -= inCharacterSpacingFraction; mEndWidthFractionMetrics[ i ] += inCharacterSpacingFraction; // note: base this on pixelsPerCharacterX, // because height of 1.0 is basic block size, not // extended (accent) size mHeightFractionMetrics[ i ] = (double)( charEndY - smallestYWithInk ) / (double)pixelsPerCharacterX; } else { // empty character image // treat as a space mStartWidthFractionMetrics[ i ] = 0; mEndWidthFractionMetrics[ i ] = inSpaceWidthFraction; mHeightFractionMetrics[ i ] = 0; } } } } else { // not using alpha (or fixed width requested) // fix width for( int i=0; i<256; i++ ) { mStartWidthFractionMetrics[ i ] = 0 - inCharacterSpacingFraction; mEndWidthFractionMetrics[ i ] = 1 + inCharacterSpacingFraction; // assume it consumes full vertical space in each block mHeightFractionMetrics[ i ] = mHWRatio; } // special case for space mStartWidthFractionMetrics[ 32 ] = 0; mEndWidthFractionMetrics[ 32 ] = inSpaceWidthFraction; } } inline double TextGL::measureTextWidth( const char *inString ) { double width = 0; int numChars = strlen( inString ); for( int i=0; i height ) { height = charHeight; } } return height; } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/gui/StickyButtonGL.h0000640000175000017500000000663711435543334024030 0ustar pabspabs/* * Modification History * * 2001-September-16 Jason Rohrer * Created. */ #ifndef STICKY_BUTTON_GL_INCLUDED #define STICKY_BUTTON_GL_INCLUDED #include "ButtonGL.h" #include "minorGems/graphics/Image.h" #include "minorGems/graphics/openGL/SingleTextureGL.h" /** * A button that can be toggled between a pressed * and unpressed state. * * @author Jason Rohrer */ class StickyButtonGL : public ButtonGL { public: /** * Constructs a button. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. * @param inUnpressedImage the image to display * when this button is unpressed. Must have dimensions * that are powers of 2. * Will be destroyed when this class is destroyed. * @param inPressedImage the image to display * when this button is pressed. Must have dimensions * that are powers of 2. * Will be destroyed when this class is destroyed. */ StickyButtonGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, Image *inUnpressedImage, Image *inPressedImage ); /** * Gets whether this button is toggled to a pressed state. * * @return true iff this button is pressed. */ virtual char isPressed(); /** * Sets this button's state. * * Note that if this function call causes * this button's state to change, then all * registered ActionListeners are notified. * * @param inPressed true iff this button should be * pressed. */ virtual void setPressed( char inPressed ); // override funxtions in GUIComponentGL virtual void mouseDragged( double inX, double inY ); virtual void mousePressed( double inX, double inY ); virtual void mouseReleased( double inX, double inY ); }; inline StickyButtonGL::StickyButtonGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, Image *inUnpressedImage, Image *inPressedImage ) : ButtonGL( inAnchorX, inAnchorY, inWidth, inHeight, inUnpressedImage, inPressedImage ) { } inline char StickyButtonGL::isPressed() { if( mCurrentTexture == mPressedTexture ) { return true; } else { return false; } } inline void StickyButtonGL::setPressed( char inPressed ) { SingleTextureGL *lastTexture = mCurrentTexture; if( inPressed ) { mCurrentTexture = mPressedTexture; } else { mCurrentTexture = mUnpressedTexture; } // check for state change if( lastTexture != mCurrentTexture ) { fireActionPerformed( this ); } } inline void StickyButtonGL::mouseDragged( double inX, double inY ) { // do nothing until the release } inline void StickyButtonGL::mousePressed( double inX, double inY ) { // do nothing until the release } inline void StickyButtonGL::mouseReleased( double inX, double inY ) { // Note the following situation: // If the mouse is pressed on another button and then // released on this button, this button will toggle... // This is non-standard behavior, but the situation occurs // rarely. By ignoring this situation, we save a bit of coding, // but this may need to be fixed later. if( isInside( inX, inY ) ) { // toggle our state to the opposite of it's current setting setPressed( !isPressed() ); // this will fire an action automatically } } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/gui/GUITranslatorGL.h0000640000175000017500000002265111435543334024056 0ustar pabspabs/* * Modification History * * 2001-September-15 Jason Rohrer * Created. * * 2001-September-16 Jason Rohrer * Changed so that translation preserves the aspect * ration of GUI components. * Fixed a bug with inverted y components of mouse coordinates. * * 2001-October-29 Jason Rohrer * Added support for focus. * * 2001-November-3 Jason Rohrer * Changed translation methods to be public. * * 2006-July-3 Jason Rohrer * Fixed warnings. Changed to be a scene handler. * Fixed problems with coordinate translation. * * 2008-October-27 Jason Rohrer * Added support for setting viewport size separate from screen size. * * 2009-December-24 Jason Rohrer * Changed behavior to be consistent with ScreenGL's square, centered viewport. * * 2009-December-25 Jason Rohrer * Added support for translated dimension ranges other than [0,1]. * * 2010-April-6 Jason Rohrer * Fixed behavior when screen image does not fill entire screen. */ #ifndef GUI_TRANSLATOR_GL_INCLUDED #define GUI_TRANSLATOR_GL_INCLUDED #include "GUIComponentGL.h" #include #include "minorGems/graphics/openGL/MouseHandlerGL.h" #include "minorGems/graphics/openGL/KeyboardHandlerGL.h" #include "minorGems/graphics/openGL/SceneHandlerGL.h" #include "minorGems/graphics/openGL/ScreenGL.h" /** * A class that translates coordinates for a gui component. * * Notes on intended use: * This class is best used as a wrapper for the entire * GL-based gui. In this case, the component passed to the * constructor would be a GUIContainerGL containing the * entire GUI. This class can be thought of as a wrapper * for interfacing size-independent GUI components to the * screen. * * @author Jason Rohrer */ class GUITranslatorGL : public MouseHandlerGL, public KeyboardHandlerGL, public SceneHandlerGL { public: /** * Constructs a translator. * * @param inComponent the component for which events * will be translated and delegated. All events will * be delegated to inComponent, regardless of whether the * events pass the inComponent->isInside() test. * Will be destroyed when this class is destroyed. * @param inScreen the screen whose size is used during * event translation. Must be destroyed by caller after * this class is destroyed. * @param inMaxDimension the translated width of the maximum * dimension of the screen. Defaults to 1.0 * The larger dimension of the screen is mapped to [0,inMaxDimension] * while the smaller dimension is mapped to a subset of this range, * centered. */ GUITranslatorGL( GUIComponentGL *inComponent, ScreenGL *inScreen, double inMaxDimension = 1.0 ); virtual ~GUITranslatorGL(); /** * Translates screen coordinates to gui coordinates. * * @param inX the x value of the screen coordinate. * @param inY the y value of the screen coordinate. * @param outX a pointer to an value in which the gui x * component will be returned. * @param outY a pointer to an value in which the gui y * component will be returned. */ void translate( int inX, int inY, double *outX, double *outY ); /** * Translates screen coordinates to gui coordinates. * * @param inX the x value of the screen coordinate. * * @return the gui x component will be returned. */ double translateX( int inX ); /** * Translates screen coordinates to gui coordinates. * * @param inX the x value of the screen coordinate. * * @return the gui x component will be returned. */ double translateY( int inY ); // implements the MouseHandlerGL interface virtual void mouseMoved( int inX, int inY ); virtual void mouseDragged( int inX, int inY ); virtual void mousePressed( int inX, int inY ); virtual void mouseReleased( int inX, int inY ); // implements the KeyboardHandlerGL interface virtual char isFocused(); virtual void keyPressed( unsigned char inKey, int inX, int inY ); virtual void specialKeyPressed( int inKey, int inX, int inY ); virtual void keyReleased( unsigned char inKey, int inX, int inY ); virtual void specialKeyReleased( int inKey, int inX, int inY ); // implements the SceneHandlerGL interface virtual void drawScene(); protected: GUIComponentGL *mComponent; ScreenGL *mScreen; double mMaxDimension; /** * Gets the factor by which screen coordinates need * to be multiplied to get gui coordinates. * * @return the translation factor to multiply by. */ double getTranslationFactor(); }; inline GUITranslatorGL::GUITranslatorGL( GUIComponentGL *inComponent, ScreenGL *inScreen, double inMaxDimension ) : mComponent( inComponent ), mScreen( inScreen ), mMaxDimension( inMaxDimension ) { } inline GUITranslatorGL::~GUITranslatorGL() { delete mComponent; } inline void GUITranslatorGL::translate( int inX, int inY, double *outX, double *outY ) { *outX = translateX( inX ); *outY = translateY( inY ); } inline double GUITranslatorGL::translateX( int inX ) { int xOffset = 0; int width = mScreen->getImageWidth(); int height = mScreen->getImageHeight(); if( width < height ) { // width is smaller, x range [0,mMaxDimension] // hangs off edge of vieport, centered xOffset = ( height - width ) / 2; } int screenWidth = mScreen->getWidth(); if( screenWidth != width ) { xOffset -= ( screenWidth - width ) / 2; } return ( inX + xOffset ) * getTranslationFactor(); } inline double GUITranslatorGL::translateY( int inY ) { int yOffset = 0; int width = mScreen->getImageWidth(); int height = mScreen->getImageHeight(); if( width > height ) { // height is smaller, y range [0,mMaxDimension] // hangs off edge of vieport, centered yOffset = ( width - height ) / 2; } int screenHeight = mScreen->getHeight(); if( screenHeight != height ) { yOffset += ( screenHeight - height ) / 2; } return ( height - inY + yOffset ) * getTranslationFactor(); } inline double GUITranslatorGL::getTranslationFactor() { double width = (double)( mScreen->getImageWidth() ); double height = (double)( mScreen->getImageHeight() ); if( width >= height ) { return mMaxDimension / width; } else { return mMaxDimension / height; } } inline void GUITranslatorGL::mouseMoved( int inX, int inY ) { mComponent->mouseMoved( translateX( inX ), translateY( inY ) ); } inline void GUITranslatorGL::mouseDragged( int inX, int inY ) { mComponent->mouseDragged( translateX( inX ), translateY( inY ) ); } inline void GUITranslatorGL::mousePressed( int inX, int inY ) { mComponent->mousePressed( translateX( inX ), translateY( inY ) ); } inline void GUITranslatorGL::mouseReleased( int inX, int inY ) { mComponent->mouseReleased( translateX( inX ), translateY( inY ) ); } inline char GUITranslatorGL::isFocused() { return mComponent->isFocused(); } inline void GUITranslatorGL::keyPressed( unsigned char inKey, int inX, int inY ) { mComponent->keyPressed( inKey, translateX( inX ), translateY( inY ) ); } inline void GUITranslatorGL::specialKeyPressed( int inKey, int inX, int inY ) { mComponent->specialKeyPressed( inKey, translateX( inX ), translateY( inY ) ); } inline void GUITranslatorGL::keyReleased( unsigned char inKey, int inX, int inY ) { mComponent->keyReleased( inKey, translateX( inX ), translateY( inY ) ); } inline void GUITranslatorGL::specialKeyReleased( int inKey, int inX, int inY ) { mComponent->specialKeyReleased( inKey, translateX( inX ), translateY( inY ) ); } inline void GUITranslatorGL::drawScene() { // setup orthographic projection matrices before // telling our component to draw itself // (thus, the component can draw in [0.0, mMaxDimension] space // with no regard to screen size) // Ack: // some of this code was adapted from NeHe's tutorial #17, // which can be found at http://nehe.gamedev.net glMatrixMode( GL_PROJECTION ); // Select The Projection Matrix glPushMatrix(); // Store The Projection Matrix glLoadIdentity(); // Reset The Projection Matrix // setup an orthographic projection for our 2d gui // the longer screen dimension gets mapped to the range [0,mMaxDimension], // and the shorter dimension maps to a subset of [0,mMaxDimension], // centered // we don't care about z for 2d gui's, so just select // the region around 0 double zStart = -1; double zEnd = 1; // because screenGL uses a square viewport, we can accomplish the above // with a very simple ortho projection in all cases glOrtho( 0, mMaxDimension, 0, mMaxDimension, zStart, zEnd ); glMatrixMode( GL_MODELVIEW ); // Select The Modelview Matrix glPushMatrix(); // Store The Modelview Matrix // set the model view matrix to the identity glLoadIdentity(); glDisable( GL_DEPTH_TEST ); glDisable( GL_CULL_FACE ); // draw our gui mComponent->fireRedraw(); glEnable( GL_DEPTH_TEST ); glEnable( GL_CULL_FACE ); // restore the matrices glMatrixMode( GL_MODELVIEW ); // Select The Modelview Matrix glPopMatrix(); // Restore The Old Modelview Matrix glMatrixMode( GL_PROJECTION ); // Select The Projection Matrix glPopMatrix(); // Restore The Old Projection Matrix } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/gui/MouseCursorRegionGL.h0000640000175000017500000000765211435543334025016 0ustar pabspabs/* * Modification History * * 2001-September-16 Jason Rohrer * Created. * * 2010-March-31 Jason Rohrer * Changed glColor3f to 4f to fix driver bug on some video cards. */ #ifndef MOUSE_CURSOR_REGION_GL_INCLUDED #define MOUSE_CURSOR_REGION_GL_INCLUDED #include "minorGems/graphics/openGL/gui/GUIComponentGL.h" #include "minorGems/graphics/Color.h" #include /** * A region in a GL-based gui where a mouse cursor * will be displayed. * * @author Jason Rohrer */ class MouseCursorRegionGL : public GUIComponentGL { public: /** * Constructs a mouse cursor region. * * @param inAnchorX the x position of the upper left corner * of this component. * @param inAnchorY the y position of the upper left corner * of this component. * @param inWidth the width of this component. * @param inHeight the height of this component. * @param inCursorFraction the fraction of the * region to be filled by the cursor. * @param inUnpressedColor the color to draw the * cursor with when the mouse is unpressed. * Will be destroyed when this class is destroyed. * @param inPressedColor the color to draw the * cursor with when the mouse is pressed. * Will be destroyed when this class is destroyed. */ MouseCursorRegionGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, double inCursorFraction, Color *inUnpressedColor, Color *inPressedColor ); ~MouseCursorRegionGL(); // override functions in GUIComponentGL virtual void mouseMoved( double inX, double inY ); virtual void mouseDragged( double inX, double inY ); virtual void mousePressed( double inX, double inY ); virtual void mouseReleased( double inX, double inY ); virtual void fireRedraw(); protected: double mCursorFraction; double mMouseLocationX; double mMouseLocationY; Color *mUnpressedColor; Color *mPressedColor; Color *mCurrentColor; }; inline MouseCursorRegionGL::MouseCursorRegionGL( double inAnchorX, double inAnchorY, double inWidth, double inHeight, double inCursorFraction, Color *inUnpressedColor, Color *inPressedColor ) : GUIComponentGL( inAnchorX, inAnchorY, inWidth, inHeight ), mCursorFraction( inCursorFraction ), mUnpressedColor( inUnpressedColor ), mPressedColor( inPressedColor ), mMouseLocationX( -1 ), mMouseLocationY( -1 ) { mCurrentColor = mUnpressedColor; } inline MouseCursorRegionGL::~MouseCursorRegionGL() { delete mUnpressedColor; delete mPressedColor; } inline void MouseCursorRegionGL::mouseMoved( double inX, double inY ) { mMouseLocationX = inX; mMouseLocationY = inY; mCurrentColor = mUnpressedColor; } inline void MouseCursorRegionGL::mouseReleased( double inX, double inY ) { mMouseLocationX = inX; mMouseLocationY = inY; mCurrentColor = mUnpressedColor; } inline void MouseCursorRegionGL::mouseDragged( double inX, double inY ) { mMouseLocationX = inX; mMouseLocationY = inY; mCurrentColor = mPressedColor; } inline void MouseCursorRegionGL::mousePressed( double inX, double inY ) { mMouseLocationX = inX; mMouseLocationY = inY; mCurrentColor = mPressedColor; } inline void MouseCursorRegionGL::fireRedraw() { if( isInside( mMouseLocationX, mMouseLocationY ) ) { // set our color glColor4f( mCurrentColor->r, mCurrentColor->g, mCurrentColor->b, 1.0f ); double cursorLineLengthX = mCursorFraction * mWidth; double cursorLineLengthY = mCursorFraction * mHeight; // horizontal line glBegin( GL_LINES ); { glVertex2d( mMouseLocationX - 0.5 * cursorLineLengthX, mMouseLocationY ); glVertex2d( mMouseLocationX + 0.5 * cursorLineLengthX, mMouseLocationY ); } glEnd(); // vertical line glBegin( GL_LINES ); { glVertex2d( mMouseLocationX, mMouseLocationY - 0.5 * cursorLineLengthY ); glVertex2d( mMouseLocationX, mMouseLocationY + 0.5 * cursorLineLengthY ); } glEnd(); } } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/testScreenGLcompile0000750000175000017500000000021411435543334024027 0ustar pabspabsg++ -g -o testScreenGL -I../../.. -lGL -lglut -lGLU -L/usr/X11R6/lib ScreenGL.cpp testScreenGL.cpp ../../../minorGems/util/random/Noise.cpp between-6+dfsg1.orig/minorGems/graphics/openGL/RedrawListenerGL.h0000640000175000017500000000153711435543334023526 0ustar pabspabs/* * Modification History * * 2001-February-4 Jason Rohrer * Created. * * 2010-April-9 Jason Rohrer * Added post-redraw events. */ #ifndef REDRAW_LISTENER_GL_INCLUDED #define REDRAW_LISTENER_GL_INCLUDED /** * Interface for an object that will be called at the beginning of * every openGL redraw. * * @author Jason Rohrer */ class RedrawListenerGL { public: virtual ~RedrawListenerGL() { } /** * Tells the redraw listener that a redraw is occuring. * * Note that the redraw operation waits for this call to return * before proceeding. */ virtual void fireRedraw() = 0; /** * Tells this redraw listener that all scenes have been drawn. * * Defaults to doing nothing. */ virtual void postRedraw() { } }; #endif between-6+dfsg1.orig/minorGems/graphics/openGL/SceneHandlerGL.h0000640000175000017500000000073511435543334023126 0ustar pabspabs/* * Modification History * * 2000-December-19 Jason Rohrer * Created. */ #ifndef SCENE_HANDLER_GL_INCLUDED #define SCENE_HANDLER_GL_INCLUDED /** * Interface for an object that can draw a scene onto a ScreenGL. * * @author Jason Rohrer */ class SceneHandlerGL { public: virtual ~SceneHandlerGL() { } /** * Draws a scene of objects into a ScreenGL. */ virtual void drawScene() = 0; }; #endif between-6+dfsg1.orig/minorGems/graphics/openGL/ScreenGL.cpp0000640000175000017500000003342711435543334022351 0ustar pabspabs/* * Modification History * * 2000-December-19 Jason Rohrer * Created. * * 2001-January-31 Jason Rohrer * Fixed a bug in the fullscreen code. * * 2001-February-4 Jason Rohrer * Added support for keyboard up functions. * Added support for redraw listeners. * Added missing initialization. * * 2001-August-29 Jason Rohrer * Added support for vectors of mouse, keyboard, and scene handlers. * * 2001-September-15 Jason Rohrer * Fixed a bug in passing redraw events to the redraw listeners. * * 2001-October-13 Jason Rohrer * Added a function for applying the view matrix transformation. * Removed unneeded code from the glutResize function. * * 2001-October-29 Jason Rohrer * Added support for focusable keyboard handlers. * * 2001-October-29 Jason Rohrer * Added support for focusable keyboard handlers. * * 2004-August-30 Jason Rohrer * Fixed distortion issues when screen aspect ratio is not 1:1. * * 2005-February-7 Jason Rohrer * Fixed bug of incorrect GL matrix stack usage. Now fog works correctly. * * 2005-February-21 Jason Rohrer * Removed incorrect call to glPopMatrix. * * 2005-March-4 Jason Rohrer * Changed to call redraw listeners before applying view transform. * * 2006-December-21 Jason Rohrer * Added functions for changing window size and switching to full screen. * * 2008-September-12 Jason Rohrer * Changed to use glutEnterGameMode for full screen at startup. * Added a 2D graphics mode. * * 2008-September-29 Jason Rohrer * Enabled ignoreKeyRepeat. * * 2008-October-27 Jason Rohrer * Prepared for alternate implementations besides GLUT. * Switched to implementation-independent keycodes. * Added support for setting viewport size separate from screen size. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ /* * Compile note: For Linux, add these library flags: * -lGL -lglut -lGLU -L/usr/X11R6/lib */ #include "ScreenGL.h" #include #include #include #include #include "minorGems/util/stringUtils.h" /* ScreenGL to be accessed by callback functions. * * Note that this is a bit of a hack, but the callbacks * require a C-function (not a C++ member) and have fixed signatures, * so there's no way to pass the current screen into the functions. * * This hack prevents multiple instances of the ScreenGL class from * being used simultaneously. */ ScreenGL *currentScreenGL; // maps GLUT-specific special key-codes (GLUT_KEY) to minorGems key codes // (MG_KEY) int mapGLUTKeyToMG( int inGLUTKey ); ScreenGL::ScreenGL( int inWide, int inHigh, char inFullScreen, const char *inWindowName, KeyboardHandlerGL *inKeyHandler, MouseHandlerGL *inMouseHandler, SceneHandlerGL *inSceneHandler ) : mWide( inWide ), mHigh( inHigh ), mImageSizeSet( false ), mImageWide( inWide ), mImageHigh( inHigh ), mFullScreen( inFullScreen ), m2DMode( false ), mViewPosition( new Vector3D( 0, 0, 0 ) ), mViewOrientation( new Angle3D( 0, 0, 0 ) ), mMouseHandlerVector( new SimpleVector() ), mKeyboardHandlerVector( new SimpleVector() ), mSceneHandlerVector( new SimpleVector() ), mRedrawListenerVector( new SimpleVector() ) { // add handlers if NULL (the default) was not passed in for them if( inMouseHandler != NULL ) { addMouseHandler( inMouseHandler ); } if( inKeyHandler != NULL ) { addKeyboardHandler( inKeyHandler ); } if( inSceneHandler != NULL ) { addSceneHandler( inSceneHandler ); } if( mFullScreen ) { glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); //| GLUT_FULLSCREEN ); } else { glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); } if( !mFullScreen ) { glutInitWindowSize( mWide, mHigh ); glutCreateWindow( inWindowName ); } else { // use game mode for full screen char *gameMode = autoSprintf( "%dx%d:32", mWide, mHigh ); glutGameModeString( gameMode ); if( glutGameModeGet( GLUT_GAME_MODE_POSSIBLE ) ) { glutEnterGameMode(); delete [] gameMode; } else { printf( "The full-screen mode %s is not available\n", gameMode ); delete [] gameMode; exit(1); } } glutIgnoreKeyRepeat( 1 ); glutKeyboardFunc( callbackKeyboard ); glutKeyboardUpFunc( callbackKeyboardUp ); glutSpecialFunc( callbackSpecialKeyboard ); glutSpecialUpFunc( callbackSpecialKeyboardUp ); glutReshapeFunc( callbackResize ); glutMotionFunc( callbackMotion ); glutMouseFunc( callbackMouse ); glutPassiveMotionFunc( callbackPassiveMotion ); glutDisplayFunc( callbackDisplay ); glutIdleFunc( callbackIdle ); glEnable( GL_DEPTH_TEST ); glEnable( GL_CULL_FACE ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glCullFace( GL_BACK ); glFrontFace( GL_CCW ); } ScreenGL::~ScreenGL() { if( mFullScreen ) { glutLeaveGameMode(); } delete mViewPosition; delete mViewOrientation; delete mRedrawListenerVector; delete mMouseHandlerVector; delete mKeyboardHandlerVector; delete mSceneHandlerVector; } void ScreenGL::start() { currentScreenGL = this; glutMainLoop(); } void ScreenGL::switchTo2DMode() { m2DMode = true; } void ScreenGL::setFullScreen() { glutFullScreen(); } void ScreenGL::changeWindowSize( int inWidth, int inHeight ) { glutReshapeWindow( inWidth, inHeight ); } void ScreenGL::applyViewTransform() { // compute view angle // default angle is 90, but we want to force a 1:1 aspect ratio to avoid // distortion. // If our screen's width is different than its height, we need to decrease // the view angle so that the angle coresponds to the smaller dimension. // This keeps the zoom factor constant in the smaller dimension. // Of course, because of the way perspective works, only one Z-slice // will have a constant zoom factor // The zSlice variable sets the distance of this slice from the picture // plane double zSlice = .31; double maxDimension = mWide; if( mHigh > mWide ) { maxDimension = mHigh; } double aspectDifference = fabs( mWide / 2 - mHigh / 2 ) / maxDimension; // default angle is 90 degrees... half the angle is PI/4 double angle = atan( tan( M_PI / 4 ) + aspectDifference / zSlice ); // double it to get the full angle angle *= 2; // convert to degrees angle = 360 * angle / ( 2 * M_PI ); // set up the projection matrix glMatrixMode( GL_PROJECTION ); glLoadIdentity(); //gluPerspective( 90, mWide / mHigh, 1, 9999 ); gluPerspective( angle, 1, 1, 9999 ); // set up the model view matrix glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); // create default view and up vectors, // then rotate them by orientation angle Vector3D *viewDirection = new Vector3D( 0, 0, 1 ); Vector3D *upDirection = new Vector3D( 0, 1, 0 ); viewDirection->rotate( mViewOrientation ); upDirection->rotate( mViewOrientation ); // get a point out in front of us in the view direction viewDirection->add( mViewPosition ); // look at takes a viewer position, // a point to look at, and an up direction gluLookAt( mViewPosition->mX, mViewPosition->mY, mViewPosition->mZ, viewDirection->mX, viewDirection->mY, viewDirection->mZ, upDirection->mX, upDirection->mY, upDirection->mZ ); delete viewDirection; delete upDirection; } void callbackResize( int inW, int inH ) { ScreenGL *s = currentScreenGL; s->mWide = inW; s->mHigh = inH; if( ! s->mImageSizeSet ) { // keep image size same as screen size s->mImageWide = inW; s->mImageHigh = inH; } int bigDimension = s->mImageWide; if( bigDimension < s->mImageHigh ) { bigDimension = s->mImageHigh; } int excessW = s->mWide - bigDimension; int excessH = s->mHigh - bigDimension; // viewport is square of biggest image dimension, centered on screen // (to ensure a 1:1 aspect ratio) glViewport( excessW / 2, excessH / 2, bigDimension, bigDimension ); /* if( s->mWide >= s->mHigh ) { int excess = s->mWide - s->mHigh; glViewport( 0, -excess / 2, s->mWide, s->mWide ); } else { int excess = s->mHigh - s->mWide; glViewport( -excess / 2, 0, s->mHigh, s->mHigh ); } */ glutPostRedisplay(); } void callbackKeyboard( unsigned char inKey, int inX, int inY ) { char someFocused = currentScreenGL->isKeyboardHandlerFocused(); // fire to all handlers for( int h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); // if some are focused, only fire to this handler if it is one // of the focused handlers if( !someFocused || handler->isFocused() ) { handler->keyPressed( inKey, inX, inY ); } } } void callbackKeyboardUp( unsigned char inKey, int inX, int inY ) { char someFocused = currentScreenGL->isKeyboardHandlerFocused(); // fire to all handlers for( int h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); // if some are focused, only fire to this handler if it is one // of the focused handlers if( !someFocused || handler->isFocused() ) { handler->keyReleased( inKey, inX, inY ); } } } void callbackSpecialKeyboard( int inKey, int inX, int inY ) { char someFocused = currentScreenGL->isKeyboardHandlerFocused(); // fire to all handlers for( int h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); // if some are focused, only fire to this handler if it is one // of the focused handlers if( !someFocused || handler->isFocused() ) { handler->specialKeyPressed( mapGLUTKeyToMG( inKey ), inX, inY ); } } } void callbackSpecialKeyboardUp( int inKey, int inX, int inY ) { char someFocused = currentScreenGL->isKeyboardHandlerFocused(); // fire to all handlers for( int h=0; hmKeyboardHandlerVector->size(); h++ ) { KeyboardHandlerGL *handler = *( currentScreenGL->mKeyboardHandlerVector->getElement( h ) ); // if some are focused, only fire to this handler if it is one // of the focused handlers if( !someFocused || handler->isFocused() ) { handler->specialKeyReleased( mapGLUTKeyToMG( inKey ), inX, inY ); } } } void callbackMotion( int inX, int inY ) { // fire to all handlers for( int h=0; hmMouseHandlerVector->size(); h++ ) { MouseHandlerGL *handler = *( currentScreenGL->mMouseHandlerVector->getElement( h ) ); handler->mouseDragged( inX, inY ); } } void callbackPassiveMotion( int inX, int inY ) { // fire to all handlers for( int h=0; hmMouseHandlerVector->size(); h++ ) { MouseHandlerGL *handler = *( currentScreenGL->mMouseHandlerVector->getElement( h ) ); handler->mouseMoved( inX, inY ); } } void callbackMouse( int inButton, int inState, int inX, int inY ) { // fire to all handlers for( int h=0; hmMouseHandlerVector->size(); h++ ) { MouseHandlerGL *handler = *( currentScreenGL->mMouseHandlerVector->getElement( h ) ); handler->mouseMoved( inX, inY ); if( inState == GLUT_DOWN ) { handler->mousePressed( inX, inY ); } else if( inState == GLUT_UP ) { handler->mouseReleased( inX, inY ); } else { printf( "Error: Unknown mouse state received from OpenGL\n" ); } } } void callbackDisplay() { ScreenGL *s = currentScreenGL; glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // fire to all redraw listeners // do this first so that they can update our view transform // this makes control much more responsive for( int r=0; rmRedrawListenerVector->size(); r++ ) { RedrawListenerGL *listener = *( s->mRedrawListenerVector->getElement( r ) ); listener->fireRedraw(); } if( ! s->m2DMode ) { // apply our view transform s->applyViewTransform(); } // fire to all handlers for( int h=0; hmSceneHandlerVector->size(); h++ ) { SceneHandlerGL *handler = *( currentScreenGL->mSceneHandlerVector->getElement( h ) ); handler->drawScene(); } glutSwapBuffers(); } void callbackIdle() { glutPostRedisplay(); } int mapGLUTKeyToMG( int inGLUTKey ) { switch( inGLUTKey ) { case GLUT_KEY_F1: return MG_KEY_F1; case GLUT_KEY_F2: return MG_KEY_F2; case GLUT_KEY_F3: return MG_KEY_F3; case GLUT_KEY_F4: return MG_KEY_F4; case GLUT_KEY_F5: return MG_KEY_F5; case GLUT_KEY_F6: return MG_KEY_F6; case GLUT_KEY_F7: return MG_KEY_F7; case GLUT_KEY_F8: return MG_KEY_F8; case GLUT_KEY_F9: return MG_KEY_F9; case GLUT_KEY_F10: return MG_KEY_F10; case GLUT_KEY_F11: return MG_KEY_F11; case GLUT_KEY_F12: return MG_KEY_F12; case GLUT_KEY_LEFT: return MG_KEY_LEFT; case GLUT_KEY_UP: return MG_KEY_UP; case GLUT_KEY_RIGHT: return MG_KEY_RIGHT; case GLUT_KEY_DOWN: return MG_KEY_DOWN; case GLUT_KEY_PAGE_UP: return MG_KEY_PAGE_UP; case GLUT_KEY_PAGE_DOWN: return MG_KEY_PAGE_DOWN; case GLUT_KEY_HOME: return MG_KEY_HOME; case GLUT_KEY_END: return MG_KEY_END; case GLUT_KEY_INSERT: return MG_KEY_INSERT; default: return 0; } } between-6+dfsg1.orig/minorGems/graphics/openGL/TestHandlerGL.h0000640000175000017500000002707211435543334023013 0ustar pabspabs/* * Modification History * * 2000-December-19 Jason Rohrer * Created. * * 2001-January-9 Jason Rohrer * Changed to use new Primitive3D implementations. * * 2001-January-16 Jason Rohrer * Changed to use new Translate3D class for drawing primitives. * * 2001-January-30 Jason Rohrer * Updated to comply with new Primitive3D interface. * * 2001-January-31 Jason Rohrer * Added definition of M_PI if not automatically defined. * Added a quit key handler. * Added multitexturing to central quad to test multitexture implementations. * Had to recommit because of lost log message. * * 2001-February-2 Jason Rohrer * Fixed a bug in the way textures were generated. * * 2001-February-24 Jason Rohrer * Fixed incorrect delete usage. * * 2001-August-29 Jason Rohrer * Fixed to use new KeyboardHandler interface. */ #ifndef TEST_HANDLER_GL_INCLUDED #define TEST_HANDLER_GL_INCLUDED #include #include #include #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #include "ScreenGL.h" #include "MouseHandlerGL.h" #include "KeyboardHandlerGL.h" #include "SceneHandlerGL.h" #include "PrimitiveGL.h" #include "ObjectGL.h" #include "minorGems/graphics/3d/LathePrimitive3D.h" #include "minorGems/graphics/3d/LandscapePrimitive3D.h" #include "TextureGL.h" #include "LightingGL.h" #include "NoLightingGL.h" #include "DirectionLightingGL.h" #include "MultiLightingGL.h" #include "minorGems/math/geometry/Vector3D.h" #include "minorGems/math/geometry/Angle3D.h" #include "minorGems/graphics/Color.h" #include "minorGems/graphics/RGBAImage.h" #include "minorGems/graphics/filters/BoxBlurFilter.h" #include "minorGems/graphics/filters/ThresholdFilter.h" #include "minorGems/graphics/filters/InvertFilter.h" #include "minorGems/util/random/RandomSource.h" #include "minorGems/util/random/Noise.h" #include "minorGems/graphics/Image.h" /** * Test class for ScreenGL implementation. * * Draws a simple polygon. * * @author Jason Rohrer */ class TestHandlerGL : public MouseHandlerGL, public KeyboardHandlerGL, public SceneHandlerGL { public: TestHandlerGL( RandomSource *inRandSource, int inNumTriangles ); ~TestHandlerGL(); /** * Sets up primitives. Must be called *after* OpenGL context is * constructed. */ void setupPrimitives(); // implement the MouseHandlerGL interface void mouseMoved( int inX, int inY ); void mouseDragged( int inX, int inY ); void mousePressed( int inX, int inY ); void mouseReleased( int inX, int inY ); // implement the KeyboardHandlerGL interface void keyPressed( unsigned char inKey, int inX, int inY ); void specialKeyPressed( int inKey, int inX, int inY ); void keyReleased( unsigned char inKey, int inX, int inY ); void specialKeyReleased( int inKey, int inX, int inY ); // implement the SceneHandlerGL interface void drawScene(); private: RandomSource *mRandSource; int mNumTriangles; Vector3D ***mTriangles; Color ***mColors; PrimitiveGL *mPrimitive; PrimitiveGL *mPrimitive2; PrimitiveGL *mPrimitive3; LightingGL *mLightingA; LightingGL *mLightingB; MultiLightingGL *mLighting; double mCurrentAngle; double mAngleStep; }; TestHandlerGL::TestHandlerGL( RandomSource *inRandSource, int inNumTriangles ) : mRandSource( inRandSource ), mNumTriangles( inNumTriangles ), mTriangles( new Vector3D**[inNumTriangles] ), mColors( new Color**[inNumTriangles] ) { mLightingA = new DirectionLightingGL( new Color( 1.0, 1.0, 1.0 ), new Vector3D( 0, 0, 1 ) ); mLightingB = new DirectionLightingGL( new Color( 0, 0, 1.0 ), new Vector3D( 1, 1, 0 ) ); mLighting = new MultiLightingGL(); mLighting->addLighting( mLightingA ); mLighting->addLighting( mLightingB ); for( int i=0; igetRandomDouble() * 10, mRandSource->getRandomDouble() * 10 - 5, mRandSource->getRandomDouble() * 10 ); mColors[i][j] = new Color( mRandSource->getRandomFloat(), mRandSource->getRandomFloat(), mRandSource->getRandomFloat(), mRandSource->getRandomFloat() ); } } } TestHandlerGL::~TestHandlerGL() { for( int i=0; igetChannel(0), textSize, textSize, fPower, true, mRandSource ); genFractalNoise2d( noiseImage->getChannel(1), textSize, textSize, fPower, true, mRandSource ); genFractalNoise2d( noiseImage->getChannel(2), textSize, textSize, fPower, true, mRandSource ); Image *selection = new Image( textSize, textSize, 1 ); genFractalNoise2d( selection->getChannel(0), textSize, textSize, fPower, true, mRandSource ); BoxBlurFilter *blur = new BoxBlurFilter( 10 ); ThresholdFilter *threshold = new ThresholdFilter( 0.5 ); InvertFilter *invert = new InvertFilter(); selection->filter( threshold ); noiseImage->setSelection( selection ); //noiseImage->filter(invert); delete blur; delete threshold; delete invert; noiseImage->clearSelection(); delete selection; /*for( int t=0; tcopy(); //double *alpha = imageArray[1]->getChannel(3); //int numPixels = imageArray[1]->getWidth() * imageArray[1]->getHeight(); //for( int p=0; psetTransparent( true ); // all passed in args will be destroyed when primitive is destroyed // setup second primitive Vector3D **latheCurve = new Vector3D*[4]; latheCurve[0] = new Vector3D( 0.5, 1, 0 ); latheCurve[1] = new Vector3D( 1, 0.5, 0 ); latheCurve[2] = new Vector3D( 1, -0.5, 0 ); latheCurve[3] = new Vector3D( 0.5, -1, 0 ); noiseImage = new RGBAImage( textSize, textSize ); genFractalNoise2d( noiseImage->getChannel(0), textSize, textSize, fPower, true, mRandSource ); genFractalNoise2d( noiseImage->getChannel(1), textSize, textSize, fPower, true, mRandSource ); genFractalNoise2d( noiseImage->getChannel(2), textSize, textSize, fPower, true, mRandSource ); Primitive3D *lathePrimitive3D = new LathePrimitive3D( 4, latheCurve, 15, 2 * M_PI, noiseImage ); lathePrimitive3D->setTransparent( false ); mPrimitive2 = new PrimitiveGL( lathePrimitive3D ); //mPrimitive2->setBackVisible( true ); // all passed in args will be destroyed when primitive is destroyed noiseImage = new RGBAImage( textSize, textSize ); genFractalNoise2d( noiseImage->getChannel(0), textSize, textSize, fPower, true, mRandSource ); genFractalNoise2d( noiseImage->getChannel(1), textSize, textSize, fPower, true, mRandSource ); genFractalNoise2d( noiseImage->getChannel(2), textSize, textSize, fPower, true, mRandSource ); int landSize = 20; unsigned long *intHeights = new unsigned long[ landSize * landSize ]; genFractalNoise2d( intHeights, landSize, landSize ); double *heights = new double[ landSize * landSize ]; for( int l=0; lr, mColors[p][v]->g, mColors[p][v]->b, mColors[p][v]->a ); glVertex3f( mTriangles[p][v]->mX, mTriangles[p][v]->mY, mTriangles[p][v]->mZ ); } } glEnd(); */ Vector3D *pos = new Vector3D( 0, 0, 10 ); Angle3D *rot = new Angle3D( mCurrentAngle, mCurrentAngle, 0 ); //Angle3D *rot = new Angle3D( 0, 0, 0 ); Transform3D *trans = new Transform3D(); trans->scale( 5 ); trans->rotate( rot ); trans->translate( pos ); //mPrimitive->setBackVisible( false ); mPrimitive->draw( trans, mLighting ); delete rot; delete pos; delete trans; pos = new Vector3D( 0, -10, 10 ); rot = new Angle3D( 0, mCurrentAngle, 0 ); trans = new Transform3D(); trans->scale( 20 ); trans->rotate( rot ); trans->translate( pos ); mPrimitive3->draw( trans, mLighting ); delete rot; delete pos; delete trans; pos = new Vector3D( 0, 5, 0 ); rot = new Angle3D( M_PI, mCurrentAngle, 0 ); trans = new Transform3D(); trans->scale( 20 ); trans->rotate( rot ); trans->translate( pos ); //mPrimitive3->setBackVisible( false ); //mPrimitive3->draw( trans, mLighting ); delete rot; delete pos; delete trans; mCurrentAngle += mAngleStep; } #endif between-6+dfsg1.orig/minorGems/graphics/openGL/TextureGL.h0000640000175000017500000002335511435543334022236 0ustar pabspabs/* * Modification History * * 2000-December-19 Jason Rohrer * Created. * * 2001-January-19 Jason Rohrer * Added support for multi-texturing. Now a TextureGL no longer has * an overall width and height (each layer can have a different size). * Also, a TextureGL no longer has an overall ID. * Got rid of an old, commented-out interface in the process. * Changed how multi-textures are blended. Settled on using MODULATE * for all layers of the texture, since nothing else produces results * that are compatible with vertex lighting. * * 2001-January-30 Jason Rohrer * Changed to check for GL version 1.2 before using 1.2 features. * Now we assume multi-texture is defined (because of the availability * of glext), but we check that it is supported at runtime. * Moved enable() below ARB function name definitions. * * 2001-January-31 Jason Rohrer * Fixed even more compile bugs. There's no need to do a multitexture * bind when setting texture data. * Removed extra checks for unneeded extensions, and fixed more compile bugs. * Fixed a bug in initMultitexture(). * Fixed a bug in disable(). */ #ifndef TEXTURE_GL_INCLUDED #define TEXTURE_GL_INCLUDED #include #include #include // try and include extensions if multitexture isn't // built-in to gl.h #ifndef GL_ARB_multitexture #include #endif /** * OpenGL 32-bit multi-layered texture map. * * @author Jason Rohrer */ class TextureGL { public: /** * Constructs a texture map. * * @param inNumLayers the number of multi-texture layers * in this texture. Currently supports a value in range [1:8]. */ TextureGL( int inNumLayers ); /** * The OpenGL texture is deleted when the TextureGL object is * destroyed. */ ~TextureGL(); /** * Sets the data for a layer of this texture. * * Blocks of 4 characters specify each pixel, and each * block must be ordered as RGBA. * * Note that width and height must each be powers of 2 and * not larger than 256 (for 3DFX compatability). Additionally, * for 3DFX compatability, the aspect ratio should not exceed 8:1. * * @param inLayer the multi-texture layer to set the data to. * @param inData a character array containing the color and alpha * components for this texture. All data is copied internally. * @param inWide width of the map in 4-byte blocks. * @param inHigh height of the map. */ void setTextureData( int inLayer, unsigned char *inData, int inWide, int inHigh ); /** * Gets the number of layers in this multi-texture. * * @return the number of layers in this multi-texture. */ int getNumLayers(); /** * Enables this texture and all of its layers. * * Note that this function only makes sense when * isMultitexturingSupported() returns true. * Otherwise, it is equivalent * to calling enable( 0 ). */ void enable(); /** * Enables a particular texture layer. * * @param inLayerNumber the layer to enable. */ void enable( int inLayerNumber ); /** * Disables this texture and all of its layers. */ void disable(); /** * Gets whether multitexturing is supported by the loaded * GL implementation. * * @return true if multitexturing is supported. */ static char isMultiTexturingSupported(); static GLenum sMultiTextureEnum[8]; private: static int sNextFreeTextureID; int mNumLayers; unsigned int *mTextureID; static const int MAX_NUM_LAYERS = 8; static char sMultiTexturingSupported; // a static initializer function static void staticInit(); static char sBeenInited; }; // initialize static members int TextureGL::sNextFreeTextureID = 13; char TextureGL::sBeenInited = false; char TextureGL::sMultiTexturingSupported = false; GLenum TextureGL::sMultiTextureEnum[MAX_NUM_LAYERS] = { GL_TEXTURE0_ARB, GL_TEXTURE1_ARB, GL_TEXTURE2_ARB, GL_TEXTURE3_ARB, GL_TEXTURE4_ARB, GL_TEXTURE5_ARB, GL_TEXTURE6_ARB, GL_TEXTURE7_ARB }; inline TextureGL::TextureGL( int inNumLayers ) : mNumLayers( inNumLayers ), mTextureID( new unsigned int[inNumLayers] ) { if( !sBeenInited ) { // call static initializer function TextureGL::staticInit(); } if( inNumLayers > MAX_NUM_LAYERS ) { printf( "TextureGL only supports 8 multi-texture layers.\n" ); printf( "The following number of layers is out of range: %d\n", inNumLayers ); } for( int i=0; i1) && string[i-1]=='\n')) { // New Extension Begins Here! other=&string[i]; pos=0; // Begin New Search while (string[i]!='\n') { // Search Whole Extension-String if (string[i]==search[pos]) pos++; // Next Position if ((pos>maxpos) && string[i+1]=='\n') return true; // We Have A Winner! i++; } } } return false; // Sorry, Not Found! } // isMultitextureSupported() Checks At Run-Time If Multitexturing Is Supported inline char initMultitexture(void) { char *extString = (char *)glGetString( GL_EXTENSIONS ); // Fetch Extension String int len = strlen( extString ); // allow for end of string character char *extensions = new char[ len + 1 ]; strcpy( extensions, extString ); for (int i=0; i #include "Color.h" class IconMap { public: IconMap( int w, int h); // construct a map of a certain width and height IconMap( int w, int h, int *offset ); // pass in precomputed y offsets into image map ~IconMap(); int wide; int high; int numPixels; int *yOffset; unsigned long *imageMap; // draw a solid IconMap into this IconMap void drawIconMap( IconMap *icon, int xPos, int yPos ); // draw a transparent IconMap into this IconMap void drawIconMapAlpha( IconMap *icon, int xPos, int yPos ); void copy( IconMap *icon ); // copy contents of another icon map into this one // does nothing if icon maps aren't the same size private: char yOffsetExternal; // is the yOffset ptr external? float invChannelMax; Color utilColor; }; inline IconMap::IconMap( int w, int h ) { invChannelMax = 1 / 255.0; wide = w; high = h; numPixels = wide * high; imageMap = new unsigned long[ wide * high ]; yOffset = new int[high]; for( int y=0; yimageMap; int *imageYOffset = icon->yOffset; int imageWide = icon->wide; int imageHigh = icon->high; // watch for buffer bounds int minY = yPos; if( minY < 0 ) { minY = 0; } int maxY = yPos + imageHigh; if( maxY > high ) { maxY = high; } int minX = xPos; if( minX < 0 ) { minX = 0; } int maxX = xPos + imageWide; if( maxX > wide ) { maxX = wide; } for( int y=minY; yimageMap; int *imageYOffset = icon->yOffset; int imageWide = icon->wide; int imageHigh = icon->high; // watch for buffer bounds int minY = yPos; if( minY < 0 ) { minY = 0; } int maxY = yPos + imageHigh; if( maxY > high ) { maxY = high; } int minX = xPos; if( minX < 0 ) { minX = 0; } int maxX = xPos + imageWide; if( maxX > wide ) { maxX = wide; } for( int y=minY; y> 24) * invChannelMax; float oneMinusAlpha = 1-alpha; unsigned long buffARGB = imageMap[ buffYContrib + x ]; argb = utilColor.getWeightedComposite( argb, alpha ); buffARGB = utilColor.getWeightedComposite( buffARGB, oneMinusAlpha ); unsigned long sum = utilColor.sumComposite( argb, buffARGB ); imageMap[ buffYContrib + x ] = sum; } } } inline void IconMap::copy( IconMap *icon ) { // make sure they are the same size if( numPixels != icon->numPixels ) { return; } // void * memcpy (void * dst, const void * src, size_t len); // each pixel is 4 bytes, so shift numPixels by 2 memcpy( (void *)(imageMap), (void *)(icon->imageMap), numPixels << 2 ); } #endif between-6+dfsg1.orig/minorGems/graphics/3d/0000750000175000017500000000000011435543334017313 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/graphics/3d/LandscapePrimitive3D.h0000640000175000017500000000776711435543334023460 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. Copied from LandscapePrimitiveGL, which this class will replace * * 2001-January-15 Jason Rohrer * Fixed a bug in the constructor. * * 2001-January-17 Jason Rohrer * Fliped how x and y in height map correspond to x and z in the terrain. * * 2001-January-19 Jason Rohrer * Changed to support multi-texturing. * * 2001-January-30 Jason Rohrer * Fixed a bug that occurs when the class defaults to no detail texture. * * 2001-March-11 Jason Rohrer * Fixed a bug in the texture map anchor points. */ #ifndef LANDSCAPE_PRIMITIVE_3D_INCLUDED #define LANDSCAPE_PRIMITIVE_3D_INCLUDED #include "Primitive3D.h" /** * Primitive 3D lanscape object. * * Made from a height map. Mesh generated spans both x and z between -1 and * 1, and can vary in height (y) from 0 to 1. * * @author Jason Rohrer */ class LandscapePrimitive3D : public Primitive3D { public: /** * Constructs a LandscapePrimitive with a multi-layer texture. * * @param inWide width of mesh in number of vertices. * Must be even and at least 2. * @param inHigh height of mesh in number of vertices. * @param inHeights array of heights for each vertex, each in * [0,1]. Must be destroyed by caller. * @param inTexture the texture to map onto the lanscape. * Texture is anchored by its corners to the corners of the * lanscape. inTexture is destroyed when primitive is destroyed. * @param inDetailTexture the second layer in the multi-texture. * The alpha channel of inDetailTexture will be used as * the blending factor to mix the detail with the global texture. * Set to NULL to use only a single layer. * @param inDetailScale the scale factor of the detailed texture. * Setting to 1.0 will anchor the detail at the corners of the * mesh (just like inTexture). Setting to 0.25 will cause * the detail texture to cycle 4 times across the surface of the * mesh. */ LandscapePrimitive3D( int inWide, int inHigh, double *inHeights, RGBAImage *inTexture, RGBAImage *inDetailTexture = NULL, double inDetailScale = 1.0 ); }; inline LandscapePrimitive3D::LandscapePrimitive3D( int inWide, int inHigh, double *inHeights, RGBAImage *inTexture, RGBAImage *inDetailTexture, double inDetailScale ) { // first, set Primitve3D members mHigh = inHigh; mWide = inWide; mNumVertices = mHigh * mWide; if( inDetailTexture == NULL ) { mNumTextures = 1; mTexture = new RGBAImage*[1]; mTexture[0] = inTexture; mAnchorX = new double*[1]; mAnchorY = new double*[1]; mAnchorX[0] = new double[mNumVertices]; mAnchorY[0] = new double[mNumVertices]; } else { mNumTextures = 2; mTexture = new RGBAImage*[2]; mTexture[0] = inTexture; mTexture[1] = inDetailTexture; mAnchorX = new double*[2]; mAnchorY = new double*[2]; mAnchorX[0] = new double[mNumVertices]; mAnchorY[0] = new double[mNumVertices]; mAnchorX[1] = new double[mNumVertices]; mAnchorY[1] = new double[mNumVertices]; } mVertices = new Vector3D*[mNumVertices]; // anchor at texture corners, and step linearly through texture double anchorYStep = 1.0 / ( mHigh - 1 ); double anchorXStep = 1.0 / ( mWide - 1 ); double detailAnchorYStep = 1.0 / ( ( mHigh - 1 ) * inDetailScale ); double detailAnchorXStep = 1.0 / ( ( mWide - 1 ) * inDetailScale ); for( int y=0; y #include "minorGems/graphics/RGBAImage.h" #include "minorGems/math/geometry/Angle3D.h" #include "minorGems/math/geometry/Vector3D.h" #include "minorGems/math/geometry/Angle3D.h" #include "minorGems/io/Serializable.h" /** * 3D primitive object. * * Comprised of a triangle mesh, texture map, and anchor points. * * @author Jason Rohrer */ class Primitive3D : public Serializable { public: /** * Constructs a Primitive. * * No parameters are copied, so they should not be destroyed * or re-accessed by caller. All are destroyed when the * primitive is destroyed. * * @param inWide width of mesh in number of vertices. * Must be even and at least 2. * @param inHigh height of mesh in number of vertices. * @param inVertices vertices in row-major order. * @param inNumTextures number of multi-texture layers for * this primitive. * @param inTexture array of textures to map onto mesh. * Note that no RGBAImage in this array should have a * selection in it. * @param inAnchorX x texture anchors for each texture and * each vertex (indexed as inAnchorX[textNum][vertNum]), * in range [0,1] (outside this range, texture will wrap). * @param inAnchorY y texture anchors for each texture and * each vertex (indexed as inAnchorY[textNum][vertNum]), * in range [0,1] (outside this range, texture will wrap). */ Primitive3D( long inWide, long inHigh, Vector3D **inVertices, long inNumTextures, RGBAImage **inTexture, double **inAnchorX, double **inAnchorY ); // construct without initializing any members // for use by subclasses and for deserialization. Primitive3D(); char mMembersAllocated; ~Primitive3D(); /** * Sets whether this primitive is transparent or not. Default * is not transparent. * * @param inTransparent true if this primitive is transparent. */ void setTransparent( char inTransparent ); /** * Gets whether this primitive is transparent or not. * * @return true iff this primitive is transparent. */ char isTransparent(); /** * Sets whether this primitive's back face is visible. Default * is not visible. * * @param inIsVisible true if the back face is visible. */ void setBackVisible( char inIsVisible ); /** * Gets whether this primitive's back face is visible or not. * * @return true iff the back face is visible. */ char isBackVisible(); /** * Gets a new instance of the derived class type. * * Should be equivalent to calling the default constructor * for the derived class type. * * Should be overridden by all derived classes that * have data members beyond those provided by Primitive3D. * Note that if the extra data members require copying, * then the copy() function should be overridden instead * of simply overriding this function. * * Primitive3D::copy() will use this function to produce * a class instance before doing a copy. * * Note that this functionality SHOULD be provided by * the built-in RTTI, but it doesn't seem to be. * * @return an instance of the derived class. */ virtual Primitive3D *getNewInstance(); /** * Copies this primitive. * * @return a copy of this primitive, which must be destroyed * by the caller. */ virtual Primitive3D *copy(); /** * Gets the number of parameters associated with this object. * * @return the number of parameters. */ virtual int getNumParameters(); /** * Gets the number of animations associated with this object. * * @return the number of animations. */ virtual int getNumAnimations(); /* * Note that the default implementations for all the parameter * and temporal animation functions do nothing. */ /** * Sets a parameter for this primative. * * @param inParameterIndex the index of the parameter to set. * If an index for a non-existing parameter is specified, * this call has no effect. * @param inValue the value to set the parameter to, in [-1, 1]. * The default value for all parameters is 0. */ virtual void setParameter( int inParameterIndex, double inValue ); /** * Gets a parameter for this primative. * * @param inParameterIndex the index of the parameter to get. * If an index for a non-existing parameter is specified, * 0 is returned. * * @return the value of the parameter, in [-1, 1]. * The default value for all parameters is 0. */ virtual double getParameter( int inParameterIndex ); /** * Steps this primitive forward in time. * * @param inStepSize the size of the timestep to take. */ virtual void step( double inStepSize ); /** * Starts a temporal animation of this primitive. * The animation progresses as step() is called repeatedly. * If called for a non-existent animation or for one that is * already running, this function has no effect. */ virtual void startAnimation( int inAnimationIndex ); /** * Stops a temporal animation of this primitive. If called * for a non-existent animation or for one that is not currently * running, this function has no effect. */ virtual void stopAnimation( int inAnimationIndex ); long mHigh, mWide; long mNumVertices; Vector3D **mVertices; Vector3D **mNormals; long mNumTextures; // Note that no RGBAImage in this array should have a // selection in it. RGBAImage **mTexture; double **mAnchorX; double **mAnchorY; // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); protected: /** * Generates standard normals from the vertices. * * If subclass is not generating normals, this * must be called before primitive is drawn, but after * the vertices have been initialized. */ void generateNormals(); char mTransparent; char mBackVisible; }; inline Primitive3D::Primitive3D( long inWide, long inHigh, Vector3D **inVertices, long inNumTextures, RGBAImage **inTexture, double **inAnchorX, double **inAnchorY ) : mHigh( inHigh ), mWide( inWide ), mNumVertices( inHigh * inWide ), mNumTextures( inNumTextures ), mVertices( inVertices ), mTexture( inTexture ), mAnchorX( inAnchorX ), mAnchorY( inAnchorY ), mTransparent( false ), mBackVisible( false ), mMembersAllocated( true ) { generateNormals(); } inline Primitive3D::Primitive3D() : mTransparent( false ), mBackVisible( false ), mMembersAllocated( false ) { } inline Primitive3D::~Primitive3D() { if( mMembersAllocated ) { int i; for( i=0; isubtract( mVertices[ index ] ); } } // now cross and add into sum for( e=0; e<4; e++ ) { if( edges[e] != NULL && edges[ (e+1) % 4 ] != NULL ) { // not that this order of crossing works // because our cross product is right handed Vector3D *normal = edges[e]->cross( edges[ (e+1) % 4 ] ); normal->normalize(); // add this normal to our sum normalSum->add( normal ); delete normal; } } // now delete edges for( e=0; e<4; e++ ) { if( edges[e] != NULL ) { delete edges[e]; } } delete [] edges; // save summed normal as normal for this point normalSum->normalize(); mNormals[index] = normalSum; } } } inline void Primitive3D::setTransparent( char inTransparent ) { mTransparent = inTransparent; } inline char Primitive3D::isTransparent() { return mTransparent; } inline void Primitive3D::setBackVisible( char inIsVisible ) { mBackVisible = inIsVisible; } inline char Primitive3D::isBackVisible() { return mBackVisible; } inline Primitive3D *Primitive3D::getNewInstance() { return new Primitive3D(); } inline Primitive3D *Primitive3D::copy() { // get an instance of the derived class, if they've // overridden getNewInstance() Primitive3D *primCopy = getNewInstance(); primCopy->mHigh = mHigh; primCopy->mWide = mWide; primCopy->mNumVertices = mNumVertices; primCopy->mVertices = new Vector3D*[mNumVertices]; primCopy->mNormals = new Vector3D*[mNumVertices]; int i; for( i=0; imVertices[i] = new Vector3D( mVertices[i] ); primCopy->mNormals[i] = new Vector3D( mNormals[i] ); } primCopy->mNumTextures = mNumTextures; primCopy->mTexture = new RGBAImage*[mNumTextures]; primCopy->mAnchorX = new double*[mNumTextures]; primCopy->mAnchorY = new double*[mNumTextures]; for( i=0; imTexture[i] = mTexture[i]->copy(); primCopy->mAnchorX[i] = new double[mNumVertices]; primCopy->mAnchorY[i] = new double[mNumVertices]; memcpy( primCopy->mAnchorX[i], mAnchorX[i], sizeof( double ) * mNumVertices ); memcpy( primCopy->mAnchorY[i], mAnchorY[i], sizeof( double ) * mNumVertices ); } primCopy->mMembersAllocated = true; primCopy->setBackVisible( isBackVisible() ); primCopy->setTransparent( isTransparent() ); return primCopy; } inline int Primitive3D::getNumParameters() { return 0; } inline int Primitive3D::getNumAnimations() { return 0; } // the base class versions of these functions do nothing inline void Primitive3D::setParameter( int inParameterIndex, double inValue ) { } inline double Primitive3D::getParameter( int inParameterIndex ) { return 0; } inline void Primitive3D::step( double inStepSize ) { } inline void Primitive3D::startAnimation( int inAnimationIndex ) { } inline void Primitive3D::stopAnimation( int inAnimationIndex ) { } inline int Primitive3D::serialize( OutputStream *inOutputStream ) { int numBytes = 0; numBytes += inOutputStream->writeLong( mWide ); numBytes += inOutputStream->writeLong( mHigh ); int i; // output vertices and normals for( i=0; iserialize( inOutputStream ); } for( i=0; iserialize( inOutputStream ); } numBytes += inOutputStream->writeLong( mNumTextures ); // output textures for( i=0; iserialize( inOutputStream ); } // output anchor arrays for( i=0; iwriteDouble( mAnchorX[i][p] ); } } for( i=0; iwriteDouble( mAnchorY[i][p] ); } } numBytes += inOutputStream->write( (unsigned char *)&mTransparent, 1 ); numBytes += inOutputStream->write( (unsigned char *)&mBackVisible, 1 ); return numBytes; } inline int Primitive3D::deserialize( InputStream *inInputStream ) { int numBytes = 0; int i; if( mMembersAllocated ) { // delete the old vertices, normals, and anchors for( i=0; ireadLong( &mWide ); numBytes += inInputStream->readLong( &mHigh ); mNumVertices = mHigh * mWide; mVertices = new Vector3D*[mNumVertices]; mNormals = new Vector3D*[mNumVertices]; // input vertices and normals for( i=0; ideserialize( inInputStream ); } for( i=0; ideserialize( inInputStream ); } // input number of textures numBytes += inInputStream->readLong( &mNumTextures ); mAnchorX = new double*[mNumTextures]; mAnchorY = new double*[mNumTextures]; mTexture = new RGBAImage*[mNumTextures]; // input textures for( i=0; ideserialize( inInputStream ); } // input anchor arrays for( i=0; ireadDouble( &( mAnchorX[i][p] ) ); } } for( i=0; ireadDouble( &( mAnchorY[i][p] ) ); } } numBytes += inInputStream->read( (unsigned char *)&mTransparent, 1 ); numBytes += inInputStream->read( (unsigned char *)&mBackVisible, 1 ); mMembersAllocated = true; return numBytesRead; } #endif between-6+dfsg1.orig/minorGems/graphics/3d/Primitive3DFactory.h0000640000175000017500000000646211435543334023164 0ustar pabspabs/* * Modification History * * 2001-March-14 Jason Rohrer * Created. * * 2001-April-1 Jason Rohrer * Added subreal entity vane class to factory. */ #ifndef PRIMITIVE_3D_FACTORY_INCLUDED #define PRIMITIVE_3D_FACTORY_INCLUDED #include "Primitive3D.h" // Run-time type identification interface (RTTI) #include // include these primitives only if we are part of subreal #ifdef SUBREAL #include "subreal/entity/EntityBodyPrimitive3D.h" #define FACTORY_ENTITY_BODY_PRIMITIVE_FLAG 1 #include "subreal/entity/EntityVanePrimitive3D.h" #define FACTORY_ENTITY_VANE_PRIMITIVE_FLAG 2 #endif // the default flag #define FACTORY_DEFAULT_PRIMITIVE_FLAG 0 /** * Class that maps Primitive3D integer subclass type flags to Primitive3D * subclass instances. * * Motivation for this class: * We want to extend Object3D to support subclass typed serialization * and deserialization without placing too much of a burden on * future Object3D subclasses. For instance, we don't want subclasses * to have to write their own de/serialization functions so that * particular Primitive3D subclasses are serialized correctly. * We can avoid this burden by writing the base Object3D serialization * code so that it uses this factory to transmit subclasses with * type informaton. * * @author Jason Rohrer */ class Primitive3DFactory { public: /** * Finds an integer subclass type flag for a primitive instance. * * @param inPrimitive the primitive to determine a flag for. Must * be destroyed by the caller. * * @return a type flag for inObject. 0 (the default Object3D * baseclass flag) will be returned if subclass determination fails. */ static int primitive3DToInt( Primitive3D *inPrimitive ); /** * Constructs a new, unitialized Primitive3D (in other words, * an Primitive3D ready for deserialization) of a subclass * type matching inTypeFlag. * * @param inTypeFlag the type flag specifying the class * of the returned primitive. * * @return an (unitialized) Primitive3D class instance with a * subclass type corresponding to inTypeFlag. If no * matching class is found, a default Primitive3D baseclass * instance is returned. Must be destroyed by the caller. */ static Primitive3D *intToPrimitive3D( int inTypeFlag ); }; inline int Primitive3DFactory::primitive3DToInt( Primitive3D *inPrimitive ) { // use RTTI to determine type of inPrimitive #ifdef SUBREAL if( typeid( *inPrimitive ) == typeid( EntityBodyPrimitive3D ) ) { return FACTORY_ENTITY_BODY_PRIMITIVE_FLAG; } else if( typeid( *inPrimitive ) == typeid( EntityVanePrimitive3D ) ) { return FACTORY_ENTITY_VANE_PRIMITIVE_FLAG; } #endif // else return the default flag return FACTORY_DEFAULT_PRIMITIVE_FLAG; } inline Primitive3D *Primitive3DFactory::intToPrimitive3D( int inTypeFlag ) { switch( inTypeFlag ) { case FACTORY_DEFAULT_PRIMITIVE_FLAG: return new Primitive3D(); break; /* these primitives are only defined if * we are part of subreal */ #ifdef SUBREAL case FACTORY_ENTITY_BODY_PRIMITIVE_FLAG: return new EntityBodyPrimitive3D(); break; case FACTORY_ENTITY_VANE_PRIMITIVE_FLAG: return new EntityVanePrimitive3D(); break; #endif default: // unknown primitive flag type return new Primitive3D(); break; } } #endif between-6+dfsg1.orig/minorGems/graphics/3d/Object3DFactory.h0000640000175000017500000000645211435543334022421 0ustar pabspabs/* * Modification History * * 2001-March-14 Jason Rohrer * Created. * * 2001-March-17 Jason Rohrer * Finished implementation. * * 2001-April-1 Jason Rohrer * Fixed flag name. */ #ifndef OBJECT_3D_FACTORY_INCLUDED #define OBJECT_3D_FACTORY_INCLUDED #include "Object3D.h" // Run-time type identification interface (RTTI) #include // include these objects only if we are part of subreal #ifdef SUBREAL #include "subreal/entity/EntityObject3D.h" #define FACTORY_ENTITY_OBJECT_FLAG 1 #endif // the default flag #define FACTORY_DEFAULT_OBJECT_FLAG 0 /** * Class that maps Object3D integer subclass type flags to Object3D * subclass instances. * * Motivation for this class: * We have Object3D instances that exist simultaneously on opposite * sides of the network (at both the client and server ends). Initially, * we just let the objects get sent to the server via the base class * Object3D serialization function. At that time, subclasses of Object3D * did nothing more than init an Object3D in a particular way. This * worked fine when we didn't have animations associated with various * Object3D subclasses, but doesn't work now that we have animation * code in various subclasses. During serialization (if the object * is sent as a generic Object3D), the animation code is lost on * the client end. We need a way for the client to pick the correct * subclass to construct for deserialization. We can encode the * various subtypes by integers, and then this factory class can * be used to construct a class of appropriate subtype before * deserialization. * * @author Jason Rohrer */ class Object3DFactory { public: /** * Finds an integer subclass type flag for an object instance. * * @param inObject the object to determine a flag for. Must * be destroyed by the caller. * * @return a type flag for inObject. 0 (the defautl Object3D * baseclass flag) will be returned if subclass determination fails. */ static int object3DToInt( Object3D *inObject ); /** * Constructs a new, unitialized Object3D (in other words, * an Object3D ready for deserialization) of a subclass * type matching inTypeFlag. * * @param inTypeFlag the type flag specifying the class * of the returned object. * * @return an (unitialized) Object3D class instance with a * subclass type corresponding to inTypeFlag. If no * matching class is found, a default Object3D baseclass * instance is returned. Must be destroyed by the caller. */ static Object3D *intToObject3D( int inTypeFlag ); }; inline int Object3DFactory::object3DToInt( Object3D *inObject ) { // use RTTI to determine type of inObject #ifdef SUBREAL if( typeid( *inObject ) == typeid( EntityObject3D ) ) { return FACTORY_ENTITY_OBJECT_FLAG; } #endif // else return the default flag return FACTORY_DEFAULT_OBJECT_FLAG; } inline Object3D *Object3DFactory::intToObject3D( int inTypeFlag ) { switch( inTypeFlag ) { case FACTORY_DEFAULT_OBJECT_FLAG: return new Object3D(); break; /* these objects are only defined if * we are part of subreal */ #ifdef SUBREAL case FACTORY_ENTITY_OBJECT_FLAG: return new EntityObject3D(); break; #endif default: // unknown object flag type return new Object3D(); break; } } #endif between-6+dfsg1.orig/minorGems/graphics/3d/Object3D.h0000640000175000017500000001700611435543334021066 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. Copied from ObjectGL. * * 2001-January-10 Jason Rohrer * Made class serializable. Added a parameterless constructor * to facilitate deserialization. * * 2001-January-15 Jason Rohrer * Fixed several bugs in the deserialize() function, as well as in the * destructor. * * 2001-January-16 Jason Rohrer * Changed to use a Transform3D instead of Vectors, Angles, and scales for * each primitive in the object. * * 2001-January-24 Jason Rohrer * Added a copy() function. * Fixed a bug in deserialize(). * Made mMembersAllocated public for copy function. * * 2001-January-26 Jason Rohrer * Fixed a bug in copy(). * * 2001-January-31 Jason Rohrer * Fixed bugs in serialize() and deserialize(). * * 2001-February-3 Jason Rohrer * Updated serialization code to use new interfaces. * * 2001-March-11 Jason Rohrer * Added support for paramatization and temporal animations. * * 2001-March-13 Jason Rohrer * Added interface for getting the number of parameters and animations. * * 2001-March-14 Jason Rohrer * Added use of Primitive3DFactory for typed subclass primitive * de/serialization. */ #ifndef OBJECT_3D_INCLUDED #define OBJECT_3D_INCLUDED #include "Primitive3D.h" #include "minorGems/math/geometry/Transform3D.h" #include "minorGems/io/Serializable.h" #include "Primitive3DFactory.h" /** * 3D object. * * Comprised of a collection of primitives. * * @author Jason Rohrer */ class Object3D : public Serializable { public: /** * Constructs an Object. * * No parameters are copied, so they should not be destroyed * or re-accessed by caller. All are destroyed when the * object is destroyed. * * @param inNumPrimitives the number of primitives in this object. * @param inPrimitives the primitives comprising this object. * @param inTransform a transform for each object. */ Object3D( long inNumPrimitives, Primitive3D **inPrimitives, Transform3D **inTransform ); Object3D(); ~Object3D(); /** * Copies this object. * * @return a copy of this object, which must be destroyed * by the caller. */ Object3D *copy(); /** * Gets the number of parameters associated with this object. * * @return the number of parameters. */ virtual int getNumParameters(); /** * Gets the number of animations associated with this object. * * @return the number of animations. */ virtual int getNumAnimations(); /* * Note that the default implementations for all the parameter * and temporal animation functions do nothing. */ /** * Sets a parameter for this object. * * @param inParameterIndex the index of the parameter to set. * If an index for a non-existing parameter is specified, * this call has no effect. * @param inValue the value to set the parameter to, in [-1, 1]. * The default value for all parameters is 0. */ virtual void setParameter( int inParameterIndex, double inValue ); /** * Gets a parameter for this object. * * @param inParameterIndex the index of the parameter to get. * If an index for a non-existing parameter is specified, * 0 is returned. * * @return the value of the parameter, in [-1, 1]. * The default value for all parameters is 0. */ virtual double getParameter( int inParameterIndex ); /** * Steps this object forward in time. * * @param inStepSize the size of the timestep to take. */ virtual void step( double inStepSize ); /** * Starts a temporal animation of this object. * The animation progresses as step() is called repeatedly. * If called for a non-existent animation or for one that is * already running, this function has no effect. */ virtual void startAnimation( int inAnimationIndex ); /** * Stops a temporal animation of this object. If called * for a non-existent animation or for one that is not currently * running, this function has no effect. */ virtual void stopAnimation( int inAnimationIndex ); long mNumPrimitives; Primitive3D **mPrimitives; Transform3D **mTransform; // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); char mMembersAllocated; }; inline Object3D::Object3D( long inNumPrimitives, Primitive3D **inPrimitives, Transform3D **inTransform ) : mNumPrimitives( inNumPrimitives ), mPrimitives( inPrimitives ), mTransform( inTransform ), mMembersAllocated( true ) { } inline Object3D::Object3D() : mMembersAllocated( false ) { } inline Object3D::~Object3D() { if( mMembersAllocated ) { for( int i=0; imNumPrimitives = mNumPrimitives; objCopy->mPrimitives = new Primitive3D*[ mNumPrimitives ]; objCopy->mTransform = new Transform3D*[ mNumPrimitives ]; int i; for( i=0; imPrimitives[i] = mPrimitives[i]->copy(); objCopy->mTransform[i] = new Transform3D( mTransform[i] ); } objCopy->mMembersAllocated = true; return objCopy; } inline int Object3D::getNumParameters() { return 0; } inline int Object3D::getNumAnimations() { return 0; } // the base class versions of these functions do nothing inline void Object3D::setParameter( int inParameterIndex, double inValue ) { } inline double Object3D::getParameter( int inParameterIndex ) { return 0; } inline void Object3D::step( double inStepSize ) { } inline void Object3D::startAnimation( int inAnimationIndex ) { } inline void Object3D::stopAnimation( int inAnimationIndex ) { } inline int Object3D::serialize( OutputStream *inOutputStream ) { int i; int numBytes = 0; numBytes += inOutputStream->writeLong( mNumPrimitives ); // write each primitive for( i=0; iwriteLong( typeFlag ); // write the primitive numBytes += mPrimitives[i]->serialize( inOutputStream ); } // write each primitive's transform for( i=0; iserialize( inOutputStream ); } return numBytes; } inline int Object3D::deserialize( InputStream *inInputStream ) { if( mMembersAllocated ) { // first, delete current contents of object for( int i=0; ireadLong( &mNumPrimitives ); printf( "receiving %d primitives\n", mNumPrimitives ); mPrimitives = new Primitive3D*[mNumPrimitives]; for( i=0; ireadLong( &typeFlag ); // construct a new object based on the type flag mPrimitives[i] = Primitive3DFactory::intToPrimitive3D( typeFlag ); // deserialize it numBytes += mPrimitives[i]->deserialize( inInputStream ); } mTransform = new Transform3D*[mNumPrimitives]; for( i=0; ideserialize( inInputStream ); } mMembersAllocated = true; return numBytes; } #endif between-6+dfsg1.orig/minorGems/graphics/3d/LathePrimitive3D.h0000640000175000017500000000650611435543334022611 0ustar pabspabs/* * Modification History * * 2001-January-9 Jason Rohrer * Created. Copied from LathePrimitiveGL, which this class will replace. * * 2001-January-19 Jason Rohrer * Changed to support multi-texturing internally, though this primitive * type doesn't use it. * * 2001-January-21 Jason Rohrer * Fixed a bug in the constructor. * * 2001-January-31 Jason Rohrer * Got rid of an unused variable. * * 2001-March-11 Jason Rohrer * Fixed a bug in the texture map anchor points. */ #ifndef LATHE_PRIMITIVE_3D_INCLUDED #define LATHE_PRIMITIVE_3D_INCLUDED #include "Primitive3D.h" /** * Primitive 3D lathe object. * * Made of a curve rotated around an axis. * * @author Jason Rohrer */ class LathePrimitive3D : public Primitive3D { public: /** * Constructs a LathePrimitive. The lathe curve is rotated * about the y axis. * * No parameters are copied, so they should not be destroyed * or re-accessed by caller. All are destroyed when the * primitive is destroyed. * * @param inNumCurvePoints number of points in curve to be lathed. * @param inCurvePoints points to be lathed. All z components * are set to 0 before lathing, so only x and y values matter. * @param inNumLatheSteps the number of quad segments around * the circumference of the lathed object. For example, * setting to 4 (with a lathe angle of 2pi) * will produce an extruded square object. * @param inNetLatheAngle total angle to sweep during lathing, * in (0,2pi]. * @param inTexture the texture to map onto the lathed object. * Texture is anchored by its corners to the ends of the lath * curve at the beginning and end of the lathe sweep */ LathePrimitive3D( int inNumCurvePoints, Vector3D **inCurvePoints, int inNumLatheSteps, double inNetLatheAngle, RGBAImage *inTexture ); }; inline LathePrimitive3D::LathePrimitive3D( int inNumCurvePoints, Vector3D **inCurvePoints, int inNumLatheSteps, double inNetLatheAngle, RGBAImage *inTexture ) { // first, set Primitve3D members mHigh = inNumCurvePoints; mWide = inNumLatheSteps + 1; mNumVertices = mHigh * mWide; mNumTextures = 1; mTexture = new RGBAImage*[1]; mTexture[0] = inTexture; double stepAngle = inNetLatheAngle / inNumLatheSteps; int i; // first, set all z values for control points to 0 for( i=0; imZ = 0; } mVertices = new Vector3D*[mNumVertices]; mAnchorX = new double*[1]; mAnchorY = new double*[1]; mAnchorX[0] = new double[mNumVertices]; mAnchorY[0] = new double[mNumVertices]; // anchor at texture corners, and step linearly through texture double anchorYStep = 1.0 / ( mHigh - 1 ); double anchorXStep = 1.0 / ( mWide - 1 ); for( int y=0; yreverseRotate( latheRotation ); delete latheRotation; } // cleanup as we go along delete inCurvePoints[y]; } delete [] inCurvePoints; generateNormals(); } #endif between-6+dfsg1.orig/minorGems/graphics/loadFile.cpp0000640000175000017500000000335011435543334021232 0ustar pabspabs#include #include #include "loadFile.h" // loads any file into the dest ptr. void loadFile( const char* fileName, long sizeInBytes, unsigned char* byteDestPtr) { FILE *f; int numBytesRead; f = fopen( fileName, "rb"); // open the file // don't load if file failed to open if( f == NULL ) { return; } numBytesRead = fread( (void*)byteDestPtr, sizeof(char), sizeInBytes, f); fclose(f); } // loads a photoshop RAW image file, 32-bit // NOTE: // This function exists because photoshop swaps the red and blue channels when // it saves a file as raw. Thus, the file stream doesn't match the way a video // card deals with 32-bit color. // This function loads the file and then swaps the appropriate bytes void loadRawFile( const char* fileName, long sizeInBytes, unsigned char* byteDestPtr) { //unsigned char tempChannel; long byteCount; FILE *f; int numBytesRead; f = fopen( fileName, "rb"); // open the file // don't load if file failed to open if( f == NULL ) { return; } numBytesRead = fread( (void*)byteDestPtr, sizeof(char), sizeInBytes, f); // now that file read, swap the red and blue channels: for( byteCount = 0; byteCount< sizeInBytes; byteCount=byteCount+4) { unsigned char alpha = byteDestPtr[byteCount+3]; byteDestPtr[byteCount+3] = byteDestPtr[byteCount+2]; byteDestPtr[byteCount+2] = byteDestPtr[byteCount+1]; byteDestPtr[byteCount+1] = byteDestPtr[byteCount]; byteDestPtr[byteCount] = alpha; /* tempChannel = byteDestPtr[byteCount]; // currently in red position byteDestPtr[byteCount] = byteDestPtr[byteCount+3]; // currently set to what's in alpha position byteDestPtr[byteCount+2] = tempChannel; */ } fclose(f); }between-6+dfsg1.orig/minorGems/graphics/converters/0000750000175000017500000000000011435543354021201 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/graphics/converters/bmpformat.txt0000640000175000017500000000611311435543334023731 0ustar pabspabs Size Description Header 14 bytes Windows Structure: BITMAPFILEHEADER Signature 2 bytes 'BM' FileSize 4 bytes File size in bytes reserved 4 bytes unused (=0) DataOffset 4 bytes File offset to Raster Data InfoHeader 40 bytes Windows Structure: BITMAPINFOHEADER Size 4 bytes Size of InfoHeader =40 Width 4 bytes Bitmap Width Height 4 bytes Bitmap Height Planes 2 bytes Number of Planes (=1) BitCount 2 bytes Bits per Pixel 1 = monochrome palette. NumColors = 1 4 = 4bit palletized. NumColors = 16 8 = 8bit palletized. NumColors = 256 16 = 16bit RGB. NumColors = 65536 (?) 24 = 24bit RGB. NumColors = 16M Compression 4 bytes Type of Compression 0 = BI_RGB no compression 1 = BI_RLE8 8bit RLE encoding 2 = BI_RLE4 4bit RLE encoding ImageSize 4 bytes (compressed) Size of Image It is valid to set this =0 if Compression = 0 XpixelsPerM 4 bytes horizontal resolution: Pixels/meter YpixelsPerM 4 bytes vertical resolution: Pixels/meter ColorsUsed 4 bytes Number of actually used colors ColorsImportant 4 bytes Number of important colors 0 = all ColorTable 4 * NumColors bytes present only if Info.BitsPerPixel <= 8 colors should be ordered by importance Red 1 byte Red intensity Green 1 byte Green intensity Blue 1 byte Blue intensity reserved 1 byte unused (=0) repeated NumColors times Raster Data Info.ImageSize bytes The pixel data between-6+dfsg1.orig/minorGems/graphics/converters/compileTestPNG0000750000175000017500000000022011435543334023754 0ustar pabspabsg++ -g -Wall -o testPNG -I../../.. testPNG.cpp PNGImageConverter.cpp ../../io/file/linux/PathLinux.cpp ../../system/unix/TimeUnix.cpp -lz -lpng between-6+dfsg1.orig/minorGems/graphics/converters/LittleEndianImageConverter.h0000640000175000017500000000521211435543334026560 0ustar pabspabs/* * Modification History * * 2001-September-22 Jason Rohrer * Created. */ #ifndef LITTLE_ENDIAN_IMAGE_CONVERTER_INCLUDED #define LITTLE_ENDIAN_IMAGE_CONVERTER_INCLUDED #include "minorGems/graphics/ImageConverter.h" /** * A base class for converters that have little endian file formats. * Basically includes little endian reading and writing functions. * * @author Jason Rohrer */ class LittleEndianImageConverter : public ImageConverter { public: // does not implement the ImageConverter interface, // which makes this class abstract. protected: /** * Writes a long value in little endian format. * * @param inLong the long value to write. * @param inStream the stream to write inLong to. */ void writeLittleEndianLong( long inLong, OutputStream *inStream ); /** * Writes a short value in little endian format. * * @param inShort the short value to write. * @param inStream the stream to write inShort to. */ void writeLittleEndianShort( short inShort, OutputStream *inStream ); /** * Reads a long value in little endian format. * * @param inStream the stream to read the long value from. * * @return the long value. */ long readLittleEndianLong( InputStream *inStream ); /** * Reads a short value in little endian format. * * @param inStream the stream to read the short value from. * * @return the short value. */ short readLittleEndianShort( InputStream *inStream ); }; inline void LittleEndianImageConverter::writeLittleEndianLong( long inLong, OutputStream *inStream ) { unsigned char buffer[4]; buffer[0] = (unsigned char)( inLong & 0xFF ); buffer[1] = (unsigned char)( ( inLong >> 8 ) & 0xFF ); buffer[2] = (unsigned char)( ( inLong >> 16 ) & 0xFF ); buffer[3] = (unsigned char)( ( inLong >> 24 ) & 0xFF ); inStream->write( buffer, 4 ); } inline long LittleEndianImageConverter::readLittleEndianLong( InputStream *inStream ) { unsigned char buffer[4]; inStream->read( buffer, 4 ); long outLong = buffer[0] | ( buffer[1] << 8 ) | ( buffer[2] << 16 ) | ( buffer[3] << 24 ); return outLong; } inline void LittleEndianImageConverter::writeLittleEndianShort( short inShort, OutputStream *inStream ) { unsigned char buffer[2]; buffer[0] = (unsigned char)( inShort & 0xFF ); buffer[1] = (unsigned char)( ( inShort >> 8 ) & 0xFF ); inStream->write( buffer, 2 ); } inline short LittleEndianImageConverter::readLittleEndianShort( InputStream *inStream ) { unsigned char buffer[2]; inStream->read( buffer, 2 ); long outShort = buffer[0] | ( buffer[1] << 8 ); return outShort; } #endif between-6+dfsg1.orig/minorGems/graphics/converters/testPNG.cpp0000640000175000017500000000200411435543334023224 0ustar pabspabs#include "PNGImageConverter.h" #include "minorGems/graphics/Image.h" #include "minorGems/io/file/FileOutputStream.h" #include "minorGems/system/Time.h" int main() { int imageSize = 640; Image testImage( imageSize, imageSize, 3, false ); // red fades toward bottom // green fades toward right double *red = testImage.getChannel( 0 ); double *green = testImage.getChannel( 1 ); for( int y=0; y #include "minorGems/graphics/Image.h" #include "BMPImageConverter.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/FileOutputStream.h" #include "minorGems/io/file/FileInputStream.h" // test function for the BMPImageConverter class int main( char inNumArgs, char**inArgs ) { if( inNumArgs != 2 ) { printf( "must pass in a file name to write to\n" ); return 1; } int length = 0; while( inArgs[1][length] != '\0' ) { length++; } File *file = new File( NULL, inArgs[1], length ); // read image in FileInputStream *stream = new FileInputStream( file ); BMPImageConverter *converter = new BMPImageConverter(); Image *image = converter->deformatImage( stream ); if( image != NULL ) { // write image back out File *fileOut = new File( NULL, "testOut.bmp", 11 ); FileOutputStream *outStream = new FileOutputStream( fileOut ); converter->formatImage( image, outStream ); delete outStream; delete image; } delete stream; delete file; delete converter; /* FileOutputStream *stream = new FileOutputStream( file ); BMPImageConverter *converter = new BMPImageConverter(); Image *image = new Image( 256, 256, 3 ); double *red = image->getChannel( 0 ); double *green = image->getChannel( 1 ); for( int y=0; ygetHeight(); y++ ) { for( int x=0; xgetWidth(); x++ ) { long index = y * image->getWidth() + x; red[index] = (double)y / (double)( image->getHeight() ); green[index] = (double)x / (double)( image->getWidth() ); //red[index] = 1.0; } } converter->formatImage( image, stream ); delete stream; // delete file explicitly delete file; delete converter; delete image; */ return 0; } between-6+dfsg1.orig/minorGems/graphics/converters/unix/0000750000175000017500000000000011435543334022162 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/graphics/converters/unix/JPEGImageConverterUnix.cpp0000640000175000017500000004047711435543334027127 0ustar pabspabs/* * Modification History * * 2001-April-27 Jason Rohrer * Created. * * 2001-April-29 Jason Rohrer * Finished implementation. * Added an optimization to formatImage, but it did not improve * performance, so it has been commented out. */ /** * Unix-specific JPEGImageConverter implementation * * Code for compression and decompression modeled after IJG's * libjpeg example code. * * For now, it use libjpeg to write converted data out to * file, and then reads it back in. */ #include "minorGems/graphics/converters/JPEGImageConverter.h" #include "minorGems/io/file/File.h" #include #include #include // include the jpeg library as a C file. // (yuk... spent way too much time trying to figure this one out!) extern "C" { #include } /* * is used for the decompression * error recovery mechanism. */ #include void JPEGImageConverter::formatImage( Image *inImage, OutputStream *inStream ) { if( inImage->getNumChannels() != 3 ) { printf( "JPEGImageConverter only works on 3-channel images.\n" ); return; } // most of this code was copied without modification from // IJG's example.c // This struct contains the JPEG compression parameters and pointers to // working space (which is allocated as needed by the JPEG library). // It is possible to have several such structures, representing multiple // compression/decompression processes, in existence at once. We refer // to any one struct (and its associated working data) as a "JPEG object". struct jpeg_compress_struct cinfo; // This struct represents a JPEG error handler. It is declared separately // because applications often want to supply a specialized error handler // (see the second half of this file for an example). But here we just // take the easy way out and use the standard error handler, which will // print a message on stderr and call exit() if compression fails. // Note that this struct must live as long as the main JPEG parameter // struct, to avoid dangling-pointer problems. struct jpeg_error_mgr jerr; // More stuff FILE * outfile; // target file JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s] int row_stride; // physical row width in image buffer // Step 1: allocate and initialize JPEG compression object // We have to set up the error handler first, in case the initialization // step fails. (Unlikely, but it could happen if you are out of memory.) // This routine fills in the contents of struct jerr, and returns jerr's // address which we place into the link field in cinfo. cinfo.err = jpeg_std_error( &jerr ); // Now we can initialize the JPEG compression object. jpeg_create_compress( &cinfo ); // Step 2: specify data destination (eg, a file) // Note: steps 2 and 3 can be done in either order. // use a temp file with a random name to make this more // thread-safe char *fileName = new char[99]; sprintf( fileName, "temp%d.dat", rand() ); // Here we use the library-supplied code to send compressed data to a // stdio stream. You can also write your own code to do something else. // VERY IMPORTANT: use "b" option to fopen() if you are on a machine that // requires it in order to write binary files. if( ( outfile = fopen( fileName, "wb" ) ) == NULL ) { printf( "can't open jpeg conversion temp file %s\n", fileName ); return; } jpeg_stdio_dest( &cinfo, outfile ); // Step 3: set parameters for compression // First we supply a description of the input image. // Four fields of the cinfo struct must be filled in: // image width and height, in pixels cinfo.image_width = inImage->getWidth(); cinfo.image_height = inImage->getHeight(); cinfo.input_components = 3; // # of color components per pixel cinfo.in_color_space = JCS_RGB; // colorspace of input image // Now use the library's routine to set default compression parameters. // (You must set at least cinfo.in_color_space before calling this, // since the defaults depend on the source color space.) jpeg_set_defaults( &cinfo ); // Now you can set any non-default parameters you wish to. // Here we just illustrate the use of // quality (quantization table) scaling: jpeg_set_quality( &cinfo, mQuality, TRUE ); // limit to baseline-JPEG values // Step 4: Start compressor // TRUE ensures that we will write a complete interchange-JPEG file. // Pass TRUE unless you are very sure of what you're doing. jpeg_start_compress( &cinfo, TRUE ); // Step 5: while (scan lines remain to be written) // jpeg_write_scanlines(...); // Here we use the library's state variable cinfo.next_scanline as the // loop counter, so that we don't have to keep track ourselves. // To keep things simple, we pass one scanline per call; you can pass // more if you wish, though. // JSAMPLEs per row in image_buffer row_stride = cinfo.image_width * 3; // channels of inImage, which we will need to pull pixel values out of double *redChannel = inImage->getChannel(0); double *greenChannel = inImage->getChannel(1); double *blueChannel = inImage->getChannel(2); // array that we will copy inImage pixels into // one scanline at a time row_pointer[0] = new JSAMPLE[ row_stride ]; //int rowNumber = 0; while( cinfo.next_scanline < cinfo.image_height ) { // jpeg_write_scanlines expects an array of pointers to scanlines. // Here the array is only one element long, but you could pass // more than one scanline at a time if that's more convenient. // make a scanline int yOffset = cinfo.next_scanline * cinfo.image_width; // for each pixel in the row for( int p=0; pgetLength(); unsigned char *fileBuffer = new unsigned char[ fileLength ]; fread( fileBuffer, 1, fileLength, inFile ); // now write the entire buffer to our output stream inStream->write( fileBuffer, fileLength ); delete [] fileBuffer; delete file; fclose( inFile ); // delete this temporary file remove( fileName ); delete [] fileName; // And we're done! } // copied this directly from IJG's example.c //extern "C" { /* * ERROR HANDLING: * * The JPEG library's standard error handler (jerror.c) is divided into * several "methods" which you can override individually. This lets you * adjust the behavior without duplicating a lot of code, which you might * have to update with each future release. * * Our example here shows how to override the "error_exit" method so that * control is returned to the library's caller when a fatal error occurs, * rather than calling exit() as the standard error_exit method does. * * We use C's setjmp/longjmp facility to return * control. This means that the * routine which calls the JPEG library must * first execute a setjmp() call to * establish the return point. We want the replacement error_exit to do a * longjmp(). But we need to make the setjmp buffer accessible to the * error_exit routine. To do this, we make a private extension of the * standard JPEG error handler object. (If we were using C++, we'd say we * were making a subclass of the regular error handler.) * * Here's the extended error handler struct: */ struct my_error_mgr { struct jpeg_error_mgr pub; /* "public" fields */ jmp_buf setjmp_buffer; /* for return to caller */ }; typedef struct my_error_mgr * my_error_ptr; /* * Here's the routine that will replace the standard error_exit method: */ METHODDEF(void) my_error_exit( j_common_ptr cinfo ) { /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ my_error_ptr myerr = (my_error_ptr)( cinfo->err ); /* Always display the message. */ /* We could postpone this until after returning, if we chose. */ (*cinfo->err->output_message)( cinfo ); /* Return control to the setjmp point */ longjmp( myerr->setjmp_buffer, 1 ); } // } Image *JPEGImageConverter::deformatImage( InputStream *inStream ) { // use a temp file with a random name to make this more // thread-safe char *fileName = new char[99]; sprintf( fileName, "temp%d.dat", rand() ); FILE *tempFile = fopen( fileName, "wb" ); if( tempFile == NULL ) { printf( "can't open jpeg conversion temp file %s\n", fileName ); return NULL; } // buffer for dumping stream to temp file unsigned char *tempBuffer = new unsigned char[1]; unsigned char previousByte = 0; // dump the JPEG stream from the input stream into tempFile // so that we can pass this file to libjpeg /* // optimization: use a buffer to prevent too many fwrite calls int bufferLength = 5000; unsigned char *fileBuffer = new unsigned char[ bufferLength ]; int currentBufferPosition = 0; while( !( tempBuffer[0] == 0xD9 && previousByte == 0xFF ) ) { previousByte = tempBuffer[0]; inStream->read( tempBuffer, 1 ); fileBuffer[currentBufferPosition] = tempBuffer[0]; if( currentBufferPosition == bufferLength - 1 ) { // at the end of the file buffer fwrite( fileBuffer, 1, bufferLength, tempFile ); currentBufferPosition = 0; } else { // keep filling the fileBuffer currentBufferPosition++; } } // now write remaining fileBuffer data to file fwrite( fileBuffer, 1, currentBufferPosition + 1, tempFile ); delete [] fileBuffer; */ // write until EOI sequence seen (0xFFD9) while( !( tempBuffer[0] == 0xD9 && previousByte == 0xFF ) ) { previousByte = tempBuffer[0]; inStream->read( tempBuffer, 1 ); fwrite( tempBuffer, 1, 1, tempFile ); } // end of jpeg stream reached. fclose( tempFile ); delete [] tempBuffer; // the remainder of this method was mostly copied from // IJG's example.c /* This struct contains the JPEG decompression parameters and pointers to * working space (which is allocated as needed by the JPEG library). */ struct jpeg_decompress_struct cinfo; /* We use our private extension JPEG error handler. * Note that this struct must live as long as the main JPEG parameter * struct, to avoid dangling-pointer problems. */ struct my_error_mgr jerr; /* More stuff */ FILE * infile; /* source file */ JSAMPARRAY buffer; /* Output row buffer */ int row_stride; /* physical row width in output buffer */ /* In this example we want to open the input * file before doing anything else, * so that the setjmp() error recovery below can assume the file is open. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that * requires it in order to read binary files. */ if( ( infile = fopen( fileName, "rb" ) ) == NULL ) { printf( "can't open jpeg conversion temp file %s\n", fileName ); return NULL; } /* Step 1: allocate and initialize JPEG decompression object */ /* We set up the normal JPEG error routines, then override error_exit. */ cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; /* Establish the setjmp return context for my_error_exit to use. */ if( setjmp( jerr.setjmp_buffer ) ) { /* If we get here, the JPEG code has signaled an error. * We need to clean up the JPEG object, * close the input file, and return. */ jpeg_destroy_decompress( &cinfo ); fclose( infile ); printf( "error in decompressing jpeg from stream.\n" ); return NULL; } /* Now we can initialize the JPEG decompression object. */ jpeg_create_decompress( &cinfo ); /* Step 2: specify data source (eg, a file) */ jpeg_stdio_src( &cinfo, infile ); /* Step 3: read file parameters with jpeg_read_header() */ (void) jpeg_read_header( &cinfo, TRUE ); /* We can ignore the return value from jpeg_read_header since * (a) suspension is not possible with the stdio data source, and * (b) we passed TRUE to reject a tables-only JPEG file as an error. * See libjpeg.doc for more info. */ /* Step 4: set parameters for decompression */ /* In this example, we don't need to change any of the defaults set by * jpeg_read_header(), so we do nothing here. */ /* Step 5: Start decompressor */ (void) jpeg_start_decompress( &cinfo ); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ /* We may need to do some setup of our own at this point before reading * the data. After jpeg_start_decompress() we have the correct scaled * output image dimensions available, as well as the output colormap * if we asked for color quantization. * In this example, we need to make an output work buffer of the right size. */ /* JSAMPLEs per row in output buffer */ int imageWidth = cinfo.output_width; int imageHeight = cinfo.output_height; // the return image with 3 channels Image *returnImage = new Image( imageWidth, imageHeight, 3, false ); // channels of returnImage, // which we will need to put pixel values into of double *redChannel = returnImage->getChannel(0); double *greenChannel = returnImage->getChannel(1); double *blueChannel = returnImage->getChannel(2); int currentIndex = 0; row_stride = cinfo.output_width * cinfo.output_components; /* Make a one-row-high sample array that * will go away when done with image */ buffer = ( *cinfo.mem->alloc_sarray ) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1 ); /* Step 6: while (scan lines remain to be read) */ /* jpeg_read_scanlines(...); */ /* Here we use the library's state variable cinfo.output_scanline as the * loop counter, so that we don't have to keep track ourselves. */ int rowNumber = 0; double inv255 = 1.0 / 255.0; while( cinfo.output_scanline < cinfo.output_height ) { /* jpeg_read_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could ask for * more than one scanline at a time if that's more convenient. */ (void) jpeg_read_scanlines( &cinfo, buffer, 1 ); // write the scanline into returnImage int yOffset = rowNumber * cinfo.output_width; // for each pixel in the row // copy it into the return image channels for( int p=0; p> 24 ) & 0xFF ); buffer[1] = (unsigned char)( ( inLong >> 16 ) & 0xFF ); buffer[2] = (unsigned char)( ( inLong >> 8 ) & 0xFF ); buffer[3] = (unsigned char)( inLong & 0xFF ); inStream->write( buffer, 4 ); } inline long BigEndianImageConverter::readBigEndianLong( InputStream *inStream ) { unsigned char buffer[4]; inStream->read( buffer, 4 ); long outLong = ( buffer[0] << 24 ) | ( buffer[1] << 16 ) | ( buffer[2] << 8 ) | buffer[3]; return outLong; } inline void BigEndianImageConverter::writeBigEndianShort( short inShort, OutputStream *inStream ) { unsigned char buffer[2]; buffer[0] = (unsigned char)( ( inShort >> 8 ) & 0xFF ); buffer[1] = (unsigned char)( inShort & 0xFF ); inStream->write( buffer, 2 ); } inline short BigEndianImageConverter::readBigEndianShort( InputStream *inStream ) { unsigned char buffer[2]; inStream->read( buffer, 2 ); long outShort = ( buffer[0] << 8 ) | buffer[1]; return outShort; } #endif between-6+dfsg1.orig/minorGems/graphics/converters/TGAImageConverter.h0000640000175000017500000002224711435543334024626 0ustar pabspabs/* * Modification History * * 2001-September-22 Jason Rohrer * Created. * * 2001-October-13 Jason Rohrer * Added support for 4-channel images. * * 2006-November-18 Jason Rohrer * Fixed two unused variable warnings. */ #ifndef TGA_IMAGE_CONVERTER_INCLUDED #define TGA_IMAGE_CONVERTER_INCLUDED #include "LittleEndianImageConverter.h" /** * TGA (Targa) implementation of the image conversion interface. * * Note that it only supports 24- and 32-bit TGA files * (and thus only 3- and 4-channel Images). * * TGA format information taken from: * http://www.cubic.org/source/archive/fileform/graphic/tga/targa.txt * * @author Jason Rohrer */ class TGAImageConverter : public LittleEndianImageConverter { public: // implement the ImageConverter interface virtual void formatImage( Image *inImage, OutputStream *inStream ); virtual Image *deformatImage( InputStream *inStream ); }; inline void TGAImageConverter::formatImage( Image *inImage, OutputStream *inStream ) { int numChannels = inImage->getNumChannels(); // make sure the image is in the right format if( numChannels != 3 && numChannels != 4 ) { printf( "Only 3- and 4-channel images can be converted to " ); printf( "the TGA format.\n" ); return; } long width = inImage->getWidth(); long height = inImage->getHeight(); long numPixels = width * height; // a buffer for writing single bytes unsigned char *byteBuffer = new unsigned char[1]; // write the identification field size // (an empty identification field) byteBuffer[0] = 0; inStream->write( byteBuffer, 1 ); // write the color map type // (no color map) byteBuffer[0] = 0; inStream->write( byteBuffer, 1 ); // write the image type code // (type 2: unmapped RGB image) byteBuffer[0] = 2; inStream->write( byteBuffer, 1 ); // no color map spec // (set to 0, though it will be ignored) unsigned char *colorMapSpec = new unsigned char[5]; int i; for( i=0; i<5; i++ ) { colorMapSpec[i] = 0; } inStream->write( colorMapSpec, 5 ); delete [] colorMapSpec; // now for the image specification // x origin coordinate writeLittleEndianShort( 0, inStream ); // y origin coordinate writeLittleEndianShort( 0, inStream ); writeLittleEndianShort( width, inStream ); writeLittleEndianShort( height, inStream ); // number of bits in pixels if( numChannels == 3 ) { byteBuffer[0] = 24; } else { byteBuffer[0] = 32; } inStream->write( byteBuffer, 1 ); // image descriptor byte if( numChannels == 3 ) { // setting to 0 specifies: // -- no attributes per pixel (for 24-bit) // -- screen origin in lower left corner // -- non-interleaved data storage byteBuffer[0] = 0; } else { // setting to 8 specifies: // -- 8 attributes per pixel (for 32-bit) (attributes are alpha bits) // -- screen origin in lower left corner // -- non-interleaved data storage byteBuffer[0] = 8; } // set bit 5 to 1 to specify screen origin in upper left corner byteBuffer[0] = byteBuffer[0] | ( 1 << 5 ); inStream->write( byteBuffer, 1 ); // We skip the image identification field, // since we set its length to 0 above. // We also skip the color map data, // since we have none (as specified above). // now we write the pixels, in BGR(A) order unsigned char *raster = new unsigned char[ numPixels * numChannels ]; double *red = inImage->getChannel( 0 ); double *green = inImage->getChannel( 1 ); double *blue = inImage->getChannel( 2 ); long rasterIndex = 0; if( numChannels == 3 ) { for( int i=0; iwrite( raster, numPixels * 3 ); } else { // numChannels == 4 double *alpha = inImage->getChannel( 3 ); for( int i=0; iwrite( raster, numPixels * numChannels ); delete [] raster; delete [] byteBuffer; } inline Image *TGAImageConverter::deformatImage( InputStream *inStream ) { // a buffer for reading single bytes unsigned char *byteBuffer = new unsigned char[1]; // read the identification field size inStream->read( byteBuffer, 1 ); int identificationFieldSize = byteBuffer[0]; // read the color map type // (only 0, or no color map, is supported) inStream->read( byteBuffer, 1 ); if( byteBuffer[0] != 0 ) { printf( "Only TGA files without colormaps can be read.\n" ); delete [] byteBuffer; return NULL; } // read the image type code // (only type 2, unmapped RGB image, is supported) inStream->read( byteBuffer, 1 ); if( byteBuffer[0] != 2 ) { printf( "Only TGA files containing unmapped RGB images can be read.\n" ); delete [] byteBuffer; return NULL; } // ignore color map spec // (skip all 5 bytes of it) unsigned char *colorMapSpec = new unsigned char[5]; inStream->read( colorMapSpec, 5 ); delete [] colorMapSpec; // now for the image specification // don't need either of these // don't set to a variable for now to avoid unused variable warnings // x origin coordinate readLittleEndianShort( inStream ); // y origin coordinate readLittleEndianShort( inStream ); long width = readLittleEndianShort( inStream ); long height = readLittleEndianShort( inStream ); long numPixels = width * height; // number of bits in pixels // only 24 bits per pixel supported inStream->read( byteBuffer, 1 ); if( byteBuffer[0] != 24 && byteBuffer[0] != 32 ) { printf( "Only 24- and 32-bit TGA files can be read.\n" ); delete [] byteBuffer; return NULL; } int numChannels = 0; if( byteBuffer[0] == 24 ) { numChannels = 3; } else { numChannels = 4; } // image descriptor byte // setting to 0 specifies: // -- no attributes per pixel (for 24-bit) // -- screen origin in lower left corner // -- non-interleaved data storage // set bit 5 to 1 to specify screen origin in upper left corner inStream->read( byteBuffer, 1 ); char originAtTop = byteBuffer[0] & ( 1 << 5 ); if( identificationFieldSize > 0 ) { // We skip the image identification field unsigned char *identificationField = new unsigned char[ identificationFieldSize ]; inStream->read( identificationField, identificationFieldSize ); delete [] identificationField; } // We also skip the color map data, // since we have none (as specified above). // now we read the pixels, in BGR(A) order unsigned char *raster = new unsigned char[ numPixels * numChannels ]; inStream->read( raster, numPixels * numChannels ); // optimization: don't init channels to black (found with profiler) Image *image = new Image( width, height, numChannels, false ); double *red = image->getChannel( 0 ); double *green = image->getChannel( 1 ); double *blue = image->getChannel( 2 ); long rasterIndex = 0; double inv255 = 1.0 / 255.0; if( numChannels == 3 ) { if( originAtTop ) { for( int i=0; i=0; y-- ) { for( int x=0; xgetChannel( 3 ); if( originAtTop ) { for( int i=0; i=0; y-- ) { int yOffset = y * width; for( int x=0; x #include #include #include #include #include void abort_(const char * s, ...) { va_list args; va_start(args, s); vfprintf(stderr, s, args); fprintf(stderr, "\n"); va_end(args); abort(); } int main() { int w = 100; int h = 100; unsigned int *data = new unsigned int[ w * h ]; // red fades toward bottom // green fades toward right unsigned int **rows = new unsigned int *[ h ]; for( int y=0; y 100 || mQuality < 0 ) { printf( "JPEG quality must be in [0,100]\n" ); mQuality = 50; } } inline void JPEGImageConverter::setQuality( int inQuality ) { mQuality = inQuality; if( mQuality > 100 || mQuality < 0 ) { printf( "JPEG quality must be in [0,100]\n" ); mQuality = 50; } } inline int JPEGImageConverter::getQuality() { return mQuality; } #endif between-6+dfsg1.orig/minorGems/graphics/converters/jpegConverterTestCompile0000750000175000017500000000020311435543334026106 0ustar pabspabsg++ -I../../.. -ljpeg -o jpegConverterTest jpegConverterTest.cpp unix/JPEGImageConverterUnix.cpp ../../io/file/linux/PathLinux.cpp between-6+dfsg1.orig/minorGems/graphics/converters/jpegConverterTest.cpp0000640000175000017500000000366311435543334025371 0ustar pabspabs/* * Modification History * * 2001-April-27 Jason Rohrer * Created. * * 2001-April-29 Jason Rohrer * Completed initial version and used to test JPEGImageConverter * successfully. */ #include #include "minorGems/graphics/Image.h" #include "JPEGImageConverter.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/FileOutputStream.h" #include "minorGems/io/file/FileInputStream.h" // test function for the BMPImageConverter class int main( char inNumArgs, char**inArgs ) { if( inNumArgs != 2 ) { printf( "must pass in a file name to write to\n" ); return 1; } int length = 0; while( inArgs[1][length] != '\0' ) { length++; } File *file = new File( NULL, inArgs[1], length ); // read image in FileInputStream *stream = new FileInputStream( file ); JPEGImageConverter *converter = new JPEGImageConverter( 50 ); Image *image = converter->deformatImage( stream ); if( image != NULL ) { // write image back out File *fileOut = new File( NULL, "testOut.jpg", 11 ); FileOutputStream *outStream = new FileOutputStream( fileOut ); converter->formatImage( image, outStream ); delete outStream; delete fileOut; delete image; } delete stream; delete converter; delete file; /* FileOutputStream *stream = new FileOutputStream( file ); JPEGImageConverter *converter = new JPEGImageConverteonverter( 50 ); Image *image = new Image( 256, 256, 3 ); double *red = image->getChannel( 0 ); double *green = image->getChannel( 1 ); for( int y=0; ygetHeight(); y++ ) { for( int x=0; xgetWidth(); x++ ) { long index = y * image->getWidth() + x; red[index] = (double)y / (double)( image->getHeight() ); green[index] = (double)x / (double)( image->getWidth() ); //red[index] = 1.0; } } converter->formatImage( image, stream ); delete stream; // delete file explicitly delete file; delete converter; delete image; */ return 0; } between-6+dfsg1.orig/minorGems/graphics/converters/PNGImageConverter.cpp0000640000175000017500000003574611435543334025202 0ustar pabspabs/* * Modification History * * 2006-November-21 Jason Rohrer * Created. * * 2010-May-18 Jason Rohrer * String parameters as const to fix warnings. */ #include "PNGImageConverter.h" #include "minorGems/util/SimpleVector.h" #include "minorGems/graphics/RGBAImage.h" //#include "lodepng.h" //#include #include PNGImageConverter::PNGImageConverter( int inCompressionLevel ) : mCompressionLevel( inCompressionLevel ) { // set up the CRC table // code taken from the PNG spec: // http://www.w3.org/TR/2003/REC-PNG-20031110/#D-CRCAppendix unsigned long c; int n, k; for( n=0; n<256; n++ ) { c = (unsigned long)n; for( k=0; k<8; k++ ) { if( c & 1 ) { c = 0xedb88320L ^ (c >> 1); } else { c = c >> 1; } } mCRCTable[n] = c; } } unsigned long PNGImageConverter::updateCRC( unsigned long inCRC, unsigned char *inData, int inLength ) { // code taken from the PNG spec: // http://www.w3.org/TR/2003/REC-PNG-20031110/#D-CRCAppendix unsigned long c = inCRC; int n; for( n=0; n> 8); } return c; } #define ADLER_BASE 65521 /* largest prime smaller than 65536 */ /** * Updates an adler32 checksum. * code found here http://www.ietf.org/rfc/rfc1950.txt * * New adlers should start with inAdler set to 1. * * @param inAdler the current state of the checksum. * @param inData the data to add. Destroyed by caller. * @param inLength the length of the data in bytes. * * @return the new checksum. */ unsigned long updateAdler32( unsigned long inAdler, unsigned char *inData, int inLength ) { unsigned long s1 = inAdler & 0xffff; unsigned long s2 = (inAdler >> 16) & 0xffff; int n; for (n = 0; n < inLength; n++) { s1 = (s1 + inData[n]) % ADLER_BASE; s2 = (s2 + s1) % ADLER_BASE; } return (s2 << 16) + s1; } void PNGImageConverter::writeChunk( const char inChunkType[4], unsigned char *inData, unsigned long inNumBytes, OutputStream *inStream ) { // chunk layout: // 4-byte length // 4-char type // data // 4-byte CRC (applied to type and data parts) // write the length writeBigEndianLong( inNumBytes, inStream ); inStream->write( (unsigned char *)inChunkType, 4 ); // start the crc unsigned long crc = updateCRC( mStartCRC, (unsigned char *)inChunkType, 4 ); if( inData != NULL ) { // chunk has data inStream->write( inData, inNumBytes ); crc = updateCRC( crc, inData, inNumBytes ); } // final step: invert the CRC crc = crc ^ 0xffffffffL; // now write the CRC writeBigEndianLong( crc, inStream ); } // callbacks for libpng io void libpngWriteCallback( png_structp png_ptr, png_bytep data, png_size_t length ) { // unpack our extra parameter void *write_io_ptr = png_get_io_ptr( png_ptr ); OutputStream *inStream = (OutputStream *)write_io_ptr; inStream->write( data, length ); } void libpngFlushCallback( png_structp png_ptr ) { // do nothing? } void PNGImageConverter::formatImage( Image *inImage, OutputStream *inStream ) { int numChannels = inImage->getNumChannels(); // make sure the image is in the right format if( numChannels != 3 && numChannels != 4 ) { printf( "Only 3- and 4-channel images can be converted to " ); printf( "the PNG format.\n" ); return; } int w = inImage->getWidth(); int h = inImage->getHeight(); //RGBAImage rgbaImage( inImage ); unsigned char *imageBytes = RGBAImage::getRGBABytes( inImage ); // libpng implementation // adapted from this: // http://zarb.org/~gc/html/libpng.html // get pointers to rows unsigned char **rows = new unsigned char *[h]; for( int y=0; ywrite( encodedBytes, encodedSize ); delete [] encodedBytes; if( true ) { return; } */ // same for all PNG images // used to check for basic transmission errors, such as line-end flipping unsigned char pngSignature[8] = { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }; inStream->write( pngSignature, 8 ); // data for IHDR chunk unsigned char headerData[13]; // width headerData[0] = (w >> 24) & 0xff; headerData[1] = (w >> 16) & 0xff; headerData[2] = (w >> 8) & 0xff; headerData[3] = w & 0xff; // height headerData[4] = (h >> 24) & 0xff; headerData[5] = (h >> 16) & 0xff; headerData[6] = (h >> 8) & 0xff; headerData[7] = h & 0xff; // bit depth headerData[8] = 8; // color type // 2 = truecolor (RGB) headerData[9] = 2; // compression method // method 0 (deflate) headerData[10] = 0; // filter method // method 0 supports 5 filter types headerData[11] = 0; // no interlace headerData[12] = 0; writeChunk( "IHDR", headerData, 13, inStream ); int numRawBytes = w * h * 3; // extra byte per scanline for filter type numRawBytes += h; unsigned char *rawScanlineBytes = new unsigned char[ numRawBytes ]; // ignore alpha channel double *channels[3]; int i; for( i=0; i<3; i++ ) { channels[i] = inImage->getChannel( i ); } int pixelNumber = 0; for( int y=0; y zlibBlock; // compression method 8 (deflate) // with a LZ77 window size parameter of w=7 // LZ77 window size is then 2^( w + 8 ), or in this case 32768 zlibBlock.push_back( 0x78 ); // flags // compression level 0 (2 bytes = 00b) // no preset dictionary (1 byte = 0b) // check bits for compression method (5 bits) // Should be such that if the 8-bit compression method, followed // by the 8-bit flags field, is viewed as a 16-bit number, // it is an even multiple of 31 // For our settings, check bits of 00001 works //zlibBlock.push_back( 0x01 ); // hack: mimic zlib here zlibBlock.push_back( 0xda ); // now ready for compressed data blocks int rawDataIndex = 0; // length field is 16 bits int maxUncompressedBlockLength = 65535; while( rawDataIndex < numRawBytes ) { // push another deflate block // first bit BFINAL // only 1 for final block // next two bits BTYPE // BTYPE=00 is an uncompressed block // remaining 5 bits ignored // Thus, we put 0x00 for uncompressed blocks that are not final // and 0x80 for final uncompressed block int bytesLeft = numRawBytes - rawDataIndex; int bytesInBlock; if( bytesLeft <= maxUncompressedBlockLength ) { // final // hack: when comparing output with zlib, noticed that it doesn't // set 0x80 for the final block, instead it uses 0x01 // For some reason, this was making the PNG unreadable // zlibBlock.push_back( 0x80 ); zlibBlock.push_back( 0x01 ); bytesInBlock = bytesLeft; } else { // not final zlibBlock.push_back( 0x00 ); bytesInBlock = maxUncompressedBlockLength; } // length in least-significant-byte-first order unsigned char firstLengthByte = bytesInBlock & 0xff; unsigned char secondLengthByte = (bytesInBlock >> 8) & 0xff; zlibBlock.push_back( firstLengthByte ); zlibBlock.push_back( secondLengthByte ); // those same length bytes inverted // (called "one's compliment" in the spec zlibBlock.push_back( firstLengthByte ^ 0xff); zlibBlock.push_back( secondLengthByte ^ 0xff ); // now the uncompressed data for( int b=0; b< bytesInBlock; b++ ) { zlibBlock.push_back( rawScanlineBytes[ rawDataIndex ] ); rawDataIndex++; } } // finally, adler32 of original data unsigned long adler = updateAdler32( 1L, rawScanlineBytes, numRawBytes ); zlibBlock.push_back( (adler >> 24) & 0xff ); zlibBlock.push_back( (adler >> 16) & 0xff ); zlibBlock.push_back( (adler >> 8) & 0xff ); zlibBlock.push_back( adler & 0xff ); // the zlib block is now complete /* // check against real zlib implementation z_stream zStream; zStream.next_in = rawScanlineBytes; zStream.avail_in = numRawBytes; zStream.total_in = 0; int outSize = 2 * numRawBytes + 100; unsigned char *zlibOutBuffer = new unsigned char[ outSize ]; zStream.next_out = zlibOutBuffer; zStream.avail_out = outSize; zStream.total_out = 0; zStream.data_type = Z_BINARY; zStream.zalloc = Z_NULL; zStream.zfree = Z_NULL; // init the stream // no compression int result; //result = deflateInit( &zStream, Z_DEFAULT_COMPRESSION); result = deflateInit( &zStream, Z_NO_COMPRESSION); if( result != Z_OK ) { printf( "zlib deflateInit error: %s\n", zStream.msg ); } // deflate and flush result = deflate( &zStream, Z_FINISH ); if( result != Z_STREAM_END ) { printf( "zlib deflate error (%d): %s\n", result, zStream.msg ); } printf( "Total in = %d, total out = %d\n", zStream.total_in, zStream.total_out ); printf( "Our raw bytes (%d):\n", numRawBytes ); int b; for( b=0; b zlibBlock.size() ) { minBytes = zlibBlock.size(); } for( b=0; bgetNumChannels() != 3 ) { printf( "Only 3-channel images can be converted to the BMP format.\n" ); return; } long width = inImage->getWidth(); long height = inImage->getHeight(); long numPixels = width * height; // each line should be padded with zeros to // end on a 4-byte boundary int numZeroPaddingBytes = ( 4 - ( width * 3 ) % 4 ) % 4; short bitCount = 24; long rasterSize = numPixels * 3; // zero padding bytes for each row rasterSize += numZeroPaddingBytes * height; // offset past two headers long offsetToRaster = 14 + 40; long fileSize = offsetToRaster + rasterSize; long compressionType = 0; long pixelsPerMeter = 2834; // both are 0 since we have no color map long colorsUsed = 0; long colorsImportant = 0; // write the header unsigned char *signature = new unsigned char[2]; signature[0] = 'B'; signature[1] = 'M'; inStream->write( signature, 2 ); delete [] signature; writeLittleEndianLong( fileSize, inStream ); writeLittleEndianLong( 0, inStream ); writeLittleEndianLong( offsetToRaster, inStream ); // write the info header // header size writeLittleEndianLong( 40, inStream ); writeLittleEndianLong( width, inStream ); writeLittleEndianLong( height, inStream ); // numPlanes writeLittleEndianShort( 1, inStream ); writeLittleEndianShort( bitCount, inStream ); writeLittleEndianLong( compressionType, inStream ); writeLittleEndianLong( rasterSize, inStream ); writeLittleEndianLong( pixelsPerMeter, inStream ); writeLittleEndianLong( pixelsPerMeter, inStream ); writeLittleEndianLong( colorsUsed, inStream ); writeLittleEndianLong( colorsImportant, inStream ); // no color table... // now write the raster unsigned char *raster = new unsigned char[ rasterSize ]; double *red = inImage->getChannel( 0 ); double *green = inImage->getChannel( 1 ); double *blue = inImage->getChannel( 2 ); // pixels are stored bottom-up, left to right // (row major order) long rasterIndex = 0; for( int y=height-1; y>=0; y-- ) { for( int x=0; xwrite( raster, rasterSize ); delete [] raster; } inline Image *BMPImageConverter::deformatImage( InputStream *inStream ) { // temp buffer used to skip data in the stream unsigned char *temp = new unsigned char[ 100 ]; // skip signature inStream->read( temp, 2 ); long fileSize = readLittleEndianLong( inStream ); // skip unused inStream->read( temp, 4 ); long rasterOffset = readLittleEndianLong( inStream ); long rasterSize = fileSize - rasterOffset; // skip size of header inStream->read( temp, 4 ); long width = readLittleEndianLong( inStream ); long height = readLittleEndianLong( inStream ); // skip planes inStream->read( temp, 2 ); short bitCount = readLittleEndianShort( inStream ); char failing = false; if( bitCount != 24 ) { printf( "Only 24-bit BMP file formats supported.\n" ); failing = true; } long compression = readLittleEndianLong( inStream ); if( compression != 0 ) { printf( "Only uncompressed BMP file formats supported.\n" ); failing = true; } // skip imageSize, resolution, and color usage information inStream->read( temp, 20 ); // now we're at the raster. // each line should be padded with zeros to // end on a 4-byte boundary int numZeroPaddingBytes = ( 4 - ( width * 3 ) % 4 ) % 4; unsigned char *raster = new unsigned char[ rasterSize ]; inStream->read( raster, rasterSize ); Image *returnImage; if( failing ) { return NULL; } else { returnImage = new Image( width, height, 3 ); double *red = returnImage->getChannel( 0 ); double *green = returnImage->getChannel( 1 ); double *blue = returnImage->getChannel( 2 ); // pixels are stored bottom-up, left to right // (row major order) long rasterIndex = 0; for( int y=height-1; y>=0; y-- ) { for( int x=0; x #include class Color { public : /** * Constructs a color. * * @param red, green, blue the components of the color, each in [0,1]. * @param alpha the alpha value in [0,1]. Defaults to 1. * @param inBuildComposite set to true to build the composite * upon construction, or false to skip building composite (faster). * Defaults to false. */ Color(float red, float green, float blue, float alpha=1, char inBuildComposite=false ); /** * Constructs a all-zero (except alpha set to 1) color with no * composite built. */ Color(); /** * Constructs an rgb color from HSV components. * * @param inHue, inSaturation, inValue the HSV components of the * color, each in [0,1]. * @param alpha the alpha value in [0,1]. Defaults to 1. * @param inBuildComposite set to true to build the composite * upon construction, or false to skip building composite (faster). * Defaults to true. * * @return an RGBA color equivalent to the HSV color. * Must be destroyed by caller. */ static Color *makeColorFromHSV( float inHue, float inSaturation, float inValue, float inAlpha=1, char inBuildComposite=false ); /** * Makes HSV values (each in range 0..1) from this RGB color. * * @param outH, outS, outV pointers to where values should be returned. */ void makeHSV( float *outH, float *outS, float *outV ); float r, g, b, a; char mCompositeBuilt; unsigned long composite; // 32-bit composite color Color *copy(); // make a copy of this color /** * Sets the RGBA values of this color. * * @param red, green, blue, alpha the values to set. * Alpha defaults to 0. */ void setValues( float red, float green, float blue, float alpha=1 ); /** * Sets the RGBA values of this color using the values from * another color. * * @param inOtherColor the color to copy values from. * Must be destroyed by caller. */ void setValues( Color *inOtherColor ); /** * Tests whether this color is equal to another color. * * @param inOtherColor the other color. * Must be destroyed by caller. * * @return true if they are equal, or false otherwise. */ char equals( Color *inOtherColor ); void print(); /** * Computes the linear weighted sum of two colors. * * @param inFirst the first color. * @param inSecond the second color. * @param inFirstWeight the weight given to the first color in the * sum. The second color is weighted (1-inFirstWeight). * * @return the sum color. Must be destroyed by caller. */ static Color *linearSum( Color *inFirst, Color *inSecond, float inFirstWeight ); // after adjusting the r, g, b, a values exterally // call this to remake the composite unsigned long unsigned long rebuildComposite(); // get largest component of R,G,B float getMax(); // alter color data by multiplying by weight void weightColor( float weight ); /** * Alters color data by multiplying by a weight color. * * @param inWeightColor the color to multiply this color by. * Must be destroyed by caller. */ void weightColor( Color *inWeightColor ); /** * Inverts this color. * * Ignores alpha channel. */ void invert(); /** * Saturates this color, ensuring that at most 2 components are * non-zero. * * Ignores alpha channel. */ void saturate(); // get component by component weighted 32-bit composite // (returns alpha unweighted) unsigned long getWeightedComposite( float weight ); // from this color unsigned long getWeightedComposite(unsigned long c1, float weight ); // from composite unsigned long sumComposite(unsigned long c1, unsigned long c2); // access this color as a three vector float &operator[](int rgbIndex); }; inline Color::Color() { r = 0; g = 0; b = 0; a = 1; mCompositeBuilt = false; composite = 0; } inline Color::Color(float red, float green, float blue, float alpha, char inBuildComposite ) { r = red; g = green; b = blue; a = alpha; if( inBuildComposite ) { rebuildComposite(); } else { composite = 0; mCompositeBuilt = false; } } inline Color *Color::makeColorFromHSV( float inHue, float inSaturation, float inValue, float inAlpha, char inBuildComposite ) { // based on pseudocode from http://www.easyrgb.com/math.php float r, g, b; if ( inSaturation == 0 ) { r = inValue; g = inValue; b = inValue; } else { float var_h = inHue * 6; // H must be < 1 if( var_h == 6 ) { var_h = 0; } float var_i = int( var_h ); // Or var_i = floor( var_h ) float var_1 = inValue * ( 1 - inSaturation ); float var_2 = inValue * ( 1 - inSaturation * ( var_h - var_i ) ); float var_3 = inValue * ( 1 - inSaturation * ( 1 - ( var_h - var_i ) ) ); if( var_i == 0 ) { r = inValue; g = var_3; b = var_1; } else if( var_i == 1 ) { r = var_2; g = inValue; b = var_1; } else if( var_i == 2 ) { r = var_1; g = inValue; b = var_3; } else if( var_i == 3 ) { r = var_1; g = var_2; b = inValue; } else if( var_i == 4 ) { r = var_3; g = var_1; b = inValue; } else { r = inValue; g = var_1; b = var_2; } } return new Color( r, g, b, inAlpha, inBuildComposite ); } inline void Color::makeHSV( float *outH, float *outS, float *outV ) { // based on pseudocode from http://www.easyrgb.com/math.php //Min. value of RGB float var_Min = r; if( g < var_Min ) { var_Min = g; } if( b < var_Min ) { var_Min = b; } //Max. value of RGB float var_Max = r; if( g > var_Max ) { var_Max = g; } if( b > var_Max ) { var_Max = b; } //Delta RGB value float del_Max = var_Max - var_Min; //HSV results from 0 to 1 float H; float S; float V = var_Max; if ( del_Max == 0 ) { //This is a gray, no chroma... H = 0; S = 0; } else { //Chromatic data... S = del_Max / var_Max; float del_R = ( ( ( var_Max - r ) / 6 ) + ( del_Max / 2 ) ) / del_Max; float del_G = ( ( ( var_Max - g ) / 6 ) + ( del_Max / 2 ) ) / del_Max; float del_B = ( ( ( var_Max - b ) / 6 ) + ( del_Max / 2 ) ) / del_Max; if( r == var_Max ) { H = del_B - del_G; } else if( g == var_Max ) { H = ( 1.0f / 3.0f ) + del_R - del_B; } else if ( b == var_Max ) { H = ( 2.0f / 3.0f ) + del_G - del_R; } if( H < 0 ) { H += 1; } if( H > 1 ) { H -= 1; } } *outH = H; *outS = S; *outV = V; } inline Color *Color::copy() { Color *copyColor = new Color(r,g,b,a, mCompositeBuilt ); return copyColor; } inline void Color::setValues( float red, float green, float blue, float alpha ) { r = red; g = green; b = blue; a = alpha; if( mCompositeBuilt ) { rebuildComposite(); } } inline void Color::setValues( Color *inOtherColor ) { setValues( inOtherColor->r, inOtherColor->g, inOtherColor->b, inOtherColor->a ); } inline char Color::equals( Color *inOtherColor ) { if( r == inOtherColor->r && g == inOtherColor->g && b == inOtherColor->b && a == inOtherColor->a ) { return true; } else { return false; } } inline void Color::print() { printf( "(%f, %f, %f, %f)", r, g, b, a ); } inline Color *Color::linearSum( Color *inFirst, Color *inSecond, float inFirstWeight ) { float secondWeight = 1 - inFirstWeight; float r = inFirstWeight * inFirst->r + secondWeight * inSecond->r; float g = inFirstWeight * inFirst->g + secondWeight * inSecond->g; float b = inFirstWeight * inFirst->b + secondWeight * inSecond->b; float a = inFirstWeight * inFirst->a + secondWeight * inSecond->a; return new Color( r, g, b, a, inFirst->mCompositeBuilt || inSecond->mCompositeBuilt ); } inline unsigned long Color::rebuildComposite() { composite = ((int)(b*255)) | ((int)(g*255)) << 8 | ((int)(r*255)) << 16 | ((int)(a*255)) << 24; mCompositeBuilt = true; return composite; } inline float Color::getMax() { float max = -FLT_MAX; if( r > max ) max = r; if( g > max ) max = g; if( b > max ) max = b; return max; } inline void Color::weightColor( float weight ) { r = r * weight; g = g * weight; b = b * weight; // for now, don't touch alpha if( mCompositeBuilt ) { rebuildComposite(); } } inline void Color::invert() { r = 1 - r; g = 1 - g; b = 1 - b; } inline void Color::saturate() { if( r < g && r < b ) { r = 0; } else if( g < r && g < b ) { g = 0; } else if( b < r && b < g ) { b = 0; } else if( r != 0 ) { // they are all equal, but non-zero // default to dropping red r = 0; } //else // they are all 0 // leave as black } inline void Color::weightColor( Color *inWeightColor ) { r *= inWeightColor->r; g *= inWeightColor->g; b *= inWeightColor->b; a *= inWeightColor->a; if( mCompositeBuilt ) { rebuildComposite(); } } inline float &Color::operator[](int rgbIndex) { if( rgbIndex == 0) return r; else if( rgbIndex == 1) return g; else if( rgbIndex == 2) return b; else if( rgbIndex == 3) return a; return r; // default, return r reference } inline unsigned long Color::getWeightedComposite( float weight ) { return ((int)(b*255*weight)) | ((int)(g*255*weight)) << 8 | ((int)(r*255*weight)) << 16 | ((int)(a*255)) << 24; } inline unsigned long Color::getWeightedComposite( unsigned long c1, float weight ) { int b = c1 & 0xFF; int g = (c1 >> 8) & 0xFF; int r = (c1 >> 16) & 0xFF; int a = c1 >> 24; return ((int)(b*weight)) | (((int)(g*weight)) << 8) | (((int)(r*weight)) << 16) | (((int)(a*weight)) << 24); } inline unsigned long Color::sumComposite(unsigned long c1, unsigned long c2) { int b = (c1 & 0xFF) + (c2 & 0xFF); if( b > 255) b = 255; int g = ((c1 >> 8) & 0xFF) + ((c2 >> 8) & 0xFF); if( g > 255) g = 255; int r = ((c1 >> 16) & 0xFF) + ((c2 >> 16) & 0xFF); if( r > 255) r = 255; int a = (c1 >> 24) + (c2 >> 24); if( a > 255) a = 255; return b | (g << 8) | (r << 16) | (a << 24); } #endif between-6+dfsg1.orig/minorGems/graphics/ImageConverter.h0000640000175000017500000000263311435543334022075 0ustar pabspabs/* * Modification History * * 2001-February-19 Jason Rohrer * Created. * * 2001-April-28 Jason Rohrer * Updated comments to deal with a failed deformatting operation. * * 2007-October-30 Jason Rohrer * Added virtual destructor. */ #ifndef IMAGE_CONVERTER_INCLUDED #define IMAGE_CONVERTER_INCLUDED #include "Image.h" #include "minorGems/io/InputStream.h" #include "minorGems/io/OutputStream.h" /** * Interface for a class that can convert Images to and from * various image formats. * * @author Jason Rohrer */ class ImageConverter { public: /** * Sends an image out to a stream as a particular * format. * * None of the parameters are destroyed by this call. * * @param inImage the image to convert. * @param inStream the stream to write the formatted image to. */ virtual void formatImage( Image *inImage, OutputStream *inStream ) = 0; /** * Reads an image in from a stream as a particular * format. * * None of the parameters are destroyed by this call. * * @param inStream the stream to read the formatted image. * * @return the deformatted image, or NULL if the deformatting * operation fails. Must be destroyed by caller. */ virtual Image *deformatImage( InputStream *inStream ) = 0; // to ensure proper destruction of implementing classes virtual ~ImageConverter() {}; }; #endif between-6+dfsg1.orig/minorGems/graphics/getMouse.h0000640000175000017500000000034211435543334020746 0ustar pabspabs// Jason Rohrer // getMouse.h /** * * general interface for getting current mouse position * Implemented by a graphix framework on a particular platform * * * Created 3-21-2000 * Mods: * */ void getMouse( int *x, int *y );between-6+dfsg1.orig/minorGems/graphics/keyCodes.h0000640000175000017500000000104411435543334020724 0ustar pabspabs// Jason Rohrer // keyCodes.h /** * * Header for defining key codes for various platforms * * * Created 12-15-99 * Mods: * Jason Rohrer 3-23-2000 Added more key codes * */ #ifdef WINDOWS_KEY_CODES #define M_KEY 0x4D #define N_KEY 0x4E #define S_KEY 0x53 #define Q_KEY 0x51 #define L_KEY 0x4C #define R_KEY 0x52 #define T_KEY 0x54 #endif #ifdef MAC_KEY_CODES #define M_KEY 0x2E #define N_KEY 0x2D #define S_KEY 0x01 #define Q_KEY 0x0C #define L_KEY 0x25 #define R_KEY 0x0F #define T_KEY 0x11 #endifbetween-6+dfsg1.orig/minorGems/graphics/linux/0000750000175000017500000000000011435543334020144 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/graphics/linux/SDLTest.cpp0000640000175000017500000001173011435543334022135 0ustar pabspabs //#include #include "minorGems/graphics/ScreenGraphics.h" #include "minorGems/graphics/GraphicBuffer.h" #include "minorGems/graphics/Color.h" #include "minorGems/ui/Mouse.h" #include #include #include int numIcons = 200; int currentStep = 0; int numSteps = 1000; void catch_int(int sig_num) { printf( "Quiting..." ); currentStep = numSteps; signal( SIGINT, catch_int); } int main() { int i, j; // let catch_int handle interrupt (^c) signal( SIGINT, catch_int); ScreenGraphics *graphics = new ScreenGraphics( 640, 480 ); Mouse *mouse = new Mouse(2); unsigned long *pixelBuff = new unsigned long[ 640 * 480 ]; GraphicBuffer *buffer = new GraphicBuffer( pixelBuff, 640, 480 ); IconMap **maps = new IconMap*[numIcons]; IconMap *mouseMap; IconMap *mouseMap1 = new IconMap( 10, 10 ); Color mouseColor1( 1.0, 0.0, 0.0, 1.0 ); for( int y=0; y<10; y++ ) { for( int x=0; x<10; x++ ) { mouseMap1->imageMap[ mouseMap1->yOffset[y] + x ] = mouseColor1.composite; } } IconMap *mouseMap2 = new IconMap( 10, 10 ); Color mouseColor2( 0.0, 1.0, 0.0, 1.0 ); for( int y=0; y<10; y++ ) { for( int x=0; x<10; x++ ) { mouseMap2->imageMap[ mouseMap2->yOffset[y] + x ] = mouseColor2.composite; } } IconMap *mouseMap3 = new IconMap( 10, 10 ); Color mouseColor3( 0.0, 0.0, 1.0, 1.0 ); for( int y=0; y<10; y++ ) { for( int x=0; x<10; x++ ) { mouseMap3->imageMap[ mouseMap3->yOffset[y] + x ] = mouseColor3.composite; } } mouseMap = mouseMap1; Color c( 0.0f, 0.0f, 0.0f, 1.0f ); buffer->fill( c ); float *xPos = new float[numIcons]; float *yPos = new float[numIcons]; float *xDelta = new float[numIcons]; float *yDelta = new float[numIcons]; for( i=0; iimageMap[ maps[i]->yOffset[y] + x ] = randColor.composite; } } } int mouseX = 0; int mouseY = 0; char buttonDown1 = false; char buttonDown2 = false; for( currentStep=0; currentSteperaseIconMap( mouseMap, mouseX, mouseY, c ); mouse->getLocation( &mouseX, &mouseY ); buffer->drawIconMap( mouseMap, mouseX, mouseY ); if( !buttonDown1 && mouse->isButtonDown(0) ) { buttonDown1 = true; mouseMap = mouseMap2; } else if( buttonDown1 && !mouse->isButtonDown(0) ) { buttonDown1 = false; mouseMap = mouseMap1; } else if( !buttonDown2 && mouse->isButtonDown(1) ) { buttonDown2 = true; mouseMap = mouseMap3; } else if( buttonDown2 && !mouse->isButtonDown(1) ) { buttonDown2 = false; mouseMap = mouseMap1; } for( i=0; ieraseIconMap( maps[i], (int)( xPos[i] - 5 ), (int)( yPos[i] - 5 ), c ); if( xPos[i] > 640 || xPos[i] < 0 ) { xDelta[i] = -xDelta[i]; } xPos[i] += xDelta[i]; if( yPos[i] > 480 || yPos[i] < 0 ) { yDelta[i] = -yDelta[i]; } yPos[i] += yDelta[i]; buffer->drawIconMap( maps[i], (int)( xPos[i] - 5 ), (int)( yPos[i] - 5 ) ); } graphics->swapBuffers( buffer ); } /* for( int i=0; i<100; i++ ) { if( i%2 == 0 ) { Color c( 1.0f, 0.0f, 0.0f, 1.0f ); buffer->fill( c ); } else { Color c( 0.0f, 1.0f, 0.0f, 1.0f ); buffer->fill( c ); } graphics->swapBuffers( buffer ); } */ printf( "Done.\n" ); return 0; /* if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { printf( "Couldn't initialize SDL: %s\n", SDL_GetError() ); exit(1); } //atexit( SDL_Quit ); SDL_Surface *screen = SDL_SetVideoMode( 640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF );//| SDL_FULLSCREEN ); if ( screen == NULL ) { printf( "Couldn't set 640x480x32 video mode: %s\n", SDL_GetError() ); exit(1); } for( int i=0; i< 100; i++ ) { if ( SDL_MUSTLOCK(screen) ) { if ( SDL_LockSurface(screen) < 0 ) { printf( "Couldn't lock screen: %s\n", SDL_GetError()); exit(1); } } Uint32 value; if( i%2 == 0 ) { value = 0x0; } else { value = 0xFFFFFFFF; } Uint32 *buffer = (Uint32 *)( screen->pixels ); for ( int y=0; yh; y++ ) { for ( int x=0; xw; x++ ) { int r = ( ( ( x * 255 ) / screen->w ) + i ) % 255; int g = ( ( ( y * 255 ) / screen->h ) + i ) % 255; int b = 0; int a = 255; //buffer[ y * screen->w + x ] = (a << 24) | (r << 16) | (g << 8) | b; buffer[ y * screen->w + x ] = value; } } if ( SDL_MUSTLOCK(screen) ) { SDL_UnlockSurface(screen); } //SDL_UpdateRect( screen, 0, 0, screen->w, screen->h ); SDL_Flip( screen ); } SDL_Quit(); SDL_Delay(2000); exit(0); */ } between-6+dfsg1.orig/minorGems/graphics/linux/ScreenGraphicsLinux.cpp0000640000175000017500000000660311435543334024576 0ustar pabspabs/* * Modification History * * 2000-November-18 Jason Rohrer * Created. * * 2000-November-19 Jason Rohrer * Change so that it doesn't use SDL's interrupt parachute, i.e., * so it will quit on ^c. * * 2001-May-1 Jason Rohrer * Changed to use more standard SDL include location. * * 2006-April-28 Jason Rohrer * Added functions for more direct access to screen pixels. * * 2006-June-26 Jason Rohrer * Added support for dirty rectangle. * Added resize support. */ #include "minorGems/graphics/ScreenGraphics.h" #include /** * Note: Linux implementation uses windowed mode. */ ScreenGraphics::ScreenGraphics( int inWidth, int inHeight ) : mWidth( inWidth ), mHeight( inHeight ) { if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE ) < 0 ) { printf( "Couldn't initialize SDL: %s\n", SDL_GetError() ); return; } SDL_Surface *screen = SDL_SetVideoMode( mWidth, mHeight, 32, SDL_SWSURFACE ); if ( screen == NULL ) { printf( "Couldn't set %dx%dx32 video mode: %s\n", mWidth, mHeight, SDL_GetError() ); return; } mNativeObjectPointer = (void*)screen; } ScreenGraphics::~ScreenGraphics() { SDL_Quit(); } void ScreenGraphics::resize( int inNewWidth, int inNewHeight ) { mWidth = inNewWidth; mHeight = inNewHeight; SDL_Surface *screen = SDL_SetVideoMode( mWidth, mHeight, 32, SDL_SWSURFACE ); if ( screen == NULL ) { printf( "Couldn't set %dx%dx32 video mode: %s\n", mWidth, mHeight, SDL_GetError() ); return; } mNativeObjectPointer = (void*)screen; } char ScreenGraphics::isResolutionAvailable( int inWidth, int inHeight ) { if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE ) < 0 ) { printf( "Couldn't initialize SDL: %s\n", SDL_GetError() ); return false; } // ask SDL if this screen size is supported char videoModeOk = (char)SDL_VideoModeOK( inWidth, inHeight, 32, SDL_SWSURFACE ); SDL_Quit(); return videoModeOk; } void ScreenGraphics::swapBuffers( GraphicBuffer *inOutBuffer ) { if( inOutBuffer->getHeight() != mHeight || inOutBuffer->getWidth() != mWidth ) { printf( "Buffer of incorrect size passed to screen.\n" ); return; } SDL_Surface *screen = (SDL_Surface*)mNativeObjectPointer; // check if we need to lock the screen if( SDL_MUSTLOCK( screen ) ) { if( SDL_LockSurface( screen ) < 0 ) { printf( "Couldn't lock screen: %s\n", SDL_GetError() ); return; } } Uint32 *buffer = (Uint32 *)( screen->pixels ); memcpy( (void*)buffer, (void*)( inOutBuffer->getBuffer() ), mWidth * mHeight * 4 ); // unlock the screen if necessary if ( SDL_MUSTLOCK(screen) ) { SDL_UnlockSurface(screen); } SDL_Flip( screen ); } GraphicBuffer *ScreenGraphics::getScreenBuffer() { SDL_Surface *screen = (SDL_Surface*)mNativeObjectPointer; Uint32 *buffer = (Uint32 *)( screen->pixels ); return new GraphicBuffer( (unsigned long *)buffer, mWidth, mHeight ); } void ScreenGraphics::flipDirtyRectangle( int inTopLeftX, int inTopLeftY, int inWidth, int inHeight ) { SDL_Surface *screen = (SDL_Surface*)mNativeObjectPointer; SDL_UpdateRect( screen, inTopLeftX, inTopLeftY, inWidth, inHeight ); } void ScreenGraphics::flipScreen() { SDL_Surface *screen = (SDL_Surface*)mNativeObjectPointer; SDL_Flip( screen ); } between-6+dfsg1.orig/minorGems/graphics/linux/graphixCommonDefs.h0000640000175000017500000000013011435543334023725 0ustar pabspabs// ALifeGUICommonDefs.h // common definitions for ALifeGui #define LINUX_KEY_CODES between-6+dfsg1.orig/minorGems/graphics/Image.h0000640000175000017500000003775011435543334020215 0ustar pabspabs/* * Modification History * * 2000-December-21 Jason Rohrer * Created. * * 2001-January-6 Jason Rohrer * Fixed a bug in filter( ChannelFilter * ). * Set mSelection to NULL by default. * * 2001-January-10 Jason Rohrer * Made class serializable. * * 2001-January-15 Jason Rohrer * Made copy() not-virtual, so it can be overridden by subclasses * while allowing pointer type to determine which function * implementation is invoked. * * 2001-January-31 Jason Rohrer * Fixed a bug in copy(). * * 2001-February-3 Jason Rohrer * Updated serialization code to use new interfaces. * * 2001-February-4 Jason Rohrer * Rewrote the serialization code to send the image across as a byte * array with one byte per channel. This will reduce the transfer size by * a factor of 8. Keeping images in double format is convennient for image * creation, but the added quality never affects the end user anyway, so * there's no point in sending the extra data to a stream. * Removed an unused array allocation. * * 2005-February-21 Jason Rohrer * Made destructor virtual to avoid compiler warnings. * * 2006-August-25 Jason Rohrer * Made zero init of pixels optional (for speed). * * 2008-September-25 Jason Rohrer * Added a sub-image function and setting/getting color functions. */ #ifndef IMAGE_INCLUDED #define IMAGE_INCLUDED #include #include #include "ChannelFilter.h" #include "Color.h" #include "minorGems/io/Serializable.h" /** * A multi-channel, double-valued image. * * Is Serializable. Note that a serialized image doesn't have a selection. * * @author Jason Rohrer */ class Image : public Serializable { public: /** * Constructs an image. * * @param inWidth width of image in pixels. * @param inHeight height of image in pixels. * @param inNumChannels number of channels in image. * @param inStartPixelsAtZero true to initialize all pixels * to zero, or false to leave default memory values (garbage) * in place (pixels must be initialized by caller in this case). * Defaults to true. */ Image( int inWidth, int inHeight, int inNumChannels, char inStartPixelsAtZero = true ); virtual ~Image(); // gets the dimensions of this image. virtual long getWidth(); virtual long getHeight(); virtual long getNumChannels(); /** * Gets the values of a particular channel. * * Values are not copied. * * @param inChannel the channel to get. * * @return the values of the specified channel in row-major order. */ virtual double *getChannel( int inChannel ); /** * Gets the 3- or 4-channel color value at a given location in the * image. * * @param inIndex the image index. * * @return a color object. */ virtual Color getColor( int inIndex ); /** * Sets the 3- or 4-channel color value at a given location in the * image. * * @param inIndex the image index. * @param inColor the new color to set. */ virtual void setColor( int inIndex, Color inColor ); /** * Selects a region of the image. Default is a clear selection, * which means all regions of image are affected by an applied * filter. * * @param inSelection the image to use as the selection mask. * Values of 0 indicate pixels that are not selection, and 1 * indicate pixels that are selected, with selection amount * varying linearly between 0 and 1. * If inSelection is a single channel, then that channel is * used as a selection mask for all channels in this image. * If inSelection contains the same number of channels as this * image, then the corresponding channels of inSelection are * are used to mask each channel of this image. * If inSelection contains a number of channels different * from the number in this image, the first channel of inSelection * is used to mask each channel in this image. * * Note that inSelection is not copied or destroyed by this class. * Thus, modifying inSelection after calling setSelection will * modify the selection in this image. */ virtual void setSelection( Image *inSelection ); /** * Gets the selection for this image. * * @return the selection for this image. Returns NULL * if there is no selection. Must not be destroyed * by caller before calling clearSelection. */ virtual Image *getSelection(); /** * Clears the selection. Effectively selects the entire image. */ virtual void clearSelection(); /** * Applies a filter to the selected region of * a specified channel of this image. * * @param inFilter the filter to apply. * @param inChannel the channel to filter. */ virtual void filter( ChannelFilter *inFilter, int inChannel ); /** * Applies a filter to the selected region of * all channels of this image. * * @param inFilter the filter to apply. */ virtual void filter( ChannelFilter *inFilter ); /** * Copies the selected region of this image. Not virtual, * so can be overridden by subclasses while allowing pointer * type to determine which function implementation is invoked. * * @return a new image with the same number of channels * as this image, each containing the selected region * from each corresponding channel of this image. Unselected * regions are set to black. Returned image has no selection. */ Image *copy(); /** * Pastes the selected region from another image into * the selected region of this image. * * @param inImage the image to paste. Let c be the number * of channels in this image, and cp be the number * of channels in the image being pasted. * If ccp, then only the first cp channels * of this image are pasted into. */ virtual void paste( Image *inImage ); /** * Copies the data from the selected region of a channel. * * @param inChannel the channel to copy. * * @return a copy of the channel data. Must be destroyed * by the caller. */ virtual double *copyChannel( int inChannel ); /** * Pastes channel data into the selected region of a specified channel. * * @param inChannelData an array containing the channel * data to be pasted. Must be destroyed by caller. * @param inChannel the channel to paste into. */ virtual void pasteChannel( double *inChannelData, int inChannel ); /** * Gets the mask for a specified channel. * * @param inChannel the channel to get a mask for. * * @return the mask data for the specified channel. * If selection has the same number of channels as this image * then a different mask is returned for each channel. Otherwise, * the first channel from the selection is returned as the * mask for every channel. Returns NULL if there is no selection. */ virtual double *getChannelSelection( int inChannel ); /** * Extracts a smaller sub-image from this image. * * Ignores current selection. * * @param inStartX, inStartY, inWidth, inHeight * coordinates for the top left corner pixel of the sub-image * and the width and height of the sub-image. * * @return the sub-image as a new image. Must be destoryed by caller. */ Image *getSubImage( int inStartX, int inStartY, int inWidth, int inHeight ); // implement the Serializable interface virtual int serialize( OutputStream *inOutputStream ); virtual int deserialize( InputStream *inInputStream ); protected: long mWide, mHigh, mNumPixels, mNumChannels; double **mChannels; // NULL if nothing selected. Image *mSelection; /** * Pastes masked channel data into the selected region of a * specified channel. * * @param inChannelData an array containing the channel * data to be pasted. Must be destroyed by caller. * @param inMask the selection mask to use for passed-in channel. * Set to NULL for no mask. * @param inChannel the channel to paste into. */ virtual void pasteChannel( double *inChannelData, double *inMask, int inChannel ); }; inline Image::Image( int inWidth, int inHeight, int inNumChannels, char inStartPixelsAtZero ) : mWide( inWidth ), mHigh( inHeight ), mNumPixels( inWidth * inHeight ), mNumChannels( inNumChannels ), mChannels( new double*[inNumChannels] ), mSelection( NULL ) { // initialize all channels for( int i=0; iapply( mChannels[ inChannel ], mWide, mHigh ); } else { // part of image selected // turn selection off and filter channel entirely Image *tempSelection = mSelection; mSelection = NULL; // filter a copy of the channel double *filteredChannel = copyChannel( inChannel ); inFilter->apply( filteredChannel, mWide, mHigh ); // now paste filtered channel back into selected region mSelection = tempSelection; pasteChannel( filteredChannel, inChannel ); } } inline void Image::filter( ChannelFilter *inFilter ) { for( int i=0; ipaste( this ); return copiedImage; } inline void Image::paste( Image *inImage ) { // copy paste in the min number of channels only int numChannelsToPaste = mNumChannels; if( numChannelsToPaste > inImage->getNumChannels() ) { numChannelsToPaste = inImage->getNumChannels(); } for( int i=0; igetChannel(i), inImage->getChannelSelection(i), i ); } } inline double *Image::copyChannel( int inChannel ) { // first, copy the channel double *copiedChannel = new double[mNumPixels]; memcpy( copiedChannel, mChannels[inChannel], sizeof( double ) * mNumPixels ); if( mSelection != NULL ) { // apply selection to copied channel double *selection = getChannelSelection( inChannel ); // scale copied channel with selection for( int i=0; igetNumChannels() == mNumChannels ) { // use separate selection for each channel return mSelection->getChannel( inChannel ); } else { // use first channel of selection for all channels return mSelection->getChannel( 0 ); } } } inline void Image::pasteChannel( double *inChannelData, int inChannel ) { pasteChannel( inChannelData, NULL, inChannel ); } // We've abstracted away the complexity in the other fuctions, // but it all seemed to filter down into this function, which // is very messy. inline void Image::pasteChannel( double *inChannelData, double *inMask, int inChannel ) { double *thisChannel = mChannels[inChannel]; if( mSelection != NULL ) { // scale incoming data with this selection double *selection = getChannelSelection(inChannel); if( inMask != NULL ) { // scale incoming data with both masks for( int i=0; igetChannel( c ); double *sourceChannel = mChannels[c]; int destY=0; for( int y=inStartY; ywriteLong( mWide ); numBytes += inOutputStream->writeLong( mHigh ); // then output number of channels numBytes += inOutputStream->writeLong( mNumChannels ); // now output each channel for( int i=0; iwriteDouble( mChannels[i][p] ); byteArray[p] = (unsigned char)( mChannels[i][p] * 255 ); } numBytes += inOutputStream->write( byteArray, mNumPixels ); delete [] byteArray; } return numBytes; } inline int Image::deserialize( InputStream *inInputStream ) { int i; // first delete old image channels for( i=0; ireadLong( &mWide ); numBytes += inInputStream->readLong( &mHigh ); mNumPixels = mWide * mHigh; // then input number of channels numBytes += inInputStream->readLong( &mNumChannels ); mChannels = new double*[mNumChannels]; // now input each channel for( i=0; iread( byteArray, mNumPixels ); // convert each byte to an 8-bit double pixel for( int p=0; preadDouble( &( mChannels[i][p] ) ); mChannels[i][p] = (double)( byteArray[p] ) / 255.0; } delete [] byteArray; } return numBytes; } #endif between-6+dfsg1.orig/minorGems/graphics/ImageColorConverter.h0000640000175000017500000003377611435543334023110 0ustar pabspabs/* * Modification History * * 2001-February-26 Jason Rohrer * Created. * Added functions for converting to and from gray byte arrays. * * 2001-September-19 Jason Rohrer * Added an RGB->HSB conversion function, which was copied * from minorGems/ai/robotics/ImageStatistics. * Added RGB<->YIQ functions. * * 2001-September-20 Jason Rohrer * Fixed a bug in the YIQ conversion. * Got rid of this bug fix, as it distorts the YIQ space, * and there is no way to prevent colors from going out of the * [0,1] range all of the time anyway. * * 2001-September-24 Jason Rohrer * Added RGB<->YCbCr functions. * Abstracted out a common coefficient multiplying function. */ #ifndef IMAGE_COLOR_CONVERTER_INCLUDED #define IMAGE_COLOR_CONVERTER_INCLUDED #include "Image.h" /** * A container class for static functions that convert * images between various color spaces. * * @author Jason Rohrer */ class ImageColorConverter { public: /** * Converts a 3-channel RGB image to a 1-channel grayscale * image using an NTSC luminosity standard. * * @param inImage the RGB image to convert. Must be destroyed * by caller. * * @return a new, grayscale version of inImage. Must be * destroyed by the caller. Returns NULL if inImage * is not a 3-channel image. */ static Image *RGBToGrayscale( Image *inImage ); /** * Converts a 1-channel grayscae image to a 3-channel RGB * image. * * @param inImage the grayscale image to convert. Must be destroyed * by caller. * * @return a new, RGB version of inImage. Must be * destroyed by the caller. Returns NULL if inImage * is not a 1-channel image. */ static Image *grayscaleToRGB( Image *inImage ); /** * Converts a 1-channel grayscae image to a 1-channel byte array. * * @param inImage the grayscale image to convert. Must be destroyed * by caller. * @param inChannelNumber the channel number to use as the * gray channel. Defaults to 0; * * @return a new byte array with one byte per image pixel, * and image [0,1] values mapped to [0,255]. */ static unsigned char *grayscaleToByteArray( Image *inImage, int inChannelNumber = 0 ); /** * Converts a byte array to a 1-channel grayscale * image. * * @param inBytes the byte array to convert. Must be destroyed * by caller. * @param inWidth the width of the image contained in the byte array. * @param inHeight the height of the image contained in the byte array. * * @return a new, grayscale image version of the byte array. Must be * destroyed by the caller. */ static Image *byteArrayToGrayscale( unsigned char *inBytes, int inWidth, int inHeight ); /** * Converts an RGB image to HSB. * * @param inRGBImage the rgb image to convert. * Must be destroyed by caller. * * @return a new image that is the HSB conversion of the * RGB image. Must be destroyed by caller. */ static Image *RGBToHSB( Image *inRGBImage ); /** * Converts an RGB image to YIQ. * * Note that color values in the resulting YIQ * image may lie outside of the range [0,1]. * * @param inRGBImage the rgb image to convert. * Must be destroyed by caller. * * @return a new image that is the YIQ conversion of the * RGB image. Must be destroyed by caller. */ static Image *RGBToYIQ( Image *inRGBImage ); /** * Converts a YIQ image to RGB. * * * Note that color values in the resulting RGB * image may lie outside of the range [0,1]. * * @param inYIQImage the rgb image to convert. * Must be destroyed by caller. * * @return a new image that is the RGB conversion of the * YIQ image. Must be destroyed by caller. */ static Image *YIQToRGB( Image *inYIQImage ); /** * Converts an RGB image to YCbCr. * * Note that in the YCbCr standard, Y is in the range * [0,1], while Cb and Cr are both in the range [-0.5, 0.5]. * This function returns Cb and Cr components shifted * into the range [0,1]. * * @param inRGBImage the rgb image to convert. * Must be destroyed by caller. * * @return a new image that is the YCbCr conversion of the * RGB image. Must be destroyed by caller. */ static Image *RGBToYCbCr( Image *inRGBImage ); /** * Converts a YCbCr image to RGB. * * * Note that in the YCbCr standard, Y is in the range * [0,1], while Cb and Cr are both in the range [-0.5, 0.5]. * This function expects input Cb and Cr components to be shifted * into the range [0,1]. * * @param inYCbCrImage the rgb image to convert. * Must be destroyed by caller. * * @return a new image that is the RGB conversion of the * YCbCr image. Must be destroyed by caller. */ static Image *YCbCrToRGB( Image *inYCbCrImage ); protected: /** * Converts an 3-channel image to another 3-channel * image using a matrix of conversion coefficients. * * The following formulae are used; * outChan0 = inC00 * inChan0 + inC01 * inChan1 + inC02 * inChan2 * outChan1 = inC10 * inChan0 + inC11 * inChan1 + inC12 * inChan2 * outChan2 = inC20 * inChan0 + inC21 * inChan1 + inC22 * inChan2 * * @param inImage the image to convert. * Must be destroyed by caller. * * @return a new image that is inImage converted, or NULL if * conversion failed (usually because inImage does not * contain 3 channels). * Must be destroyed by caller. */ static Image *coefficientConvert( Image *inImage, double inC00, double inC01, double inC02, double inC10, double inC11, double inC12, double inC20, double inC21, double inC22 ); }; inline Image *ImageColorConverter::RGBToGrayscale( Image *inImage ) { int w = inImage->getWidth(); int h = inImage->getHeight(); int numPixels = w * h; Image *grayImage = new Image( w, h, 1 ); double *red = inImage->getChannel( 0 ); double *green = inImage->getChannel( 1 ); double *blue = inImage->getChannel( 2 ); double *gray = grayImage->getChannel( 0 ); for( int i=0; igetWidth(); int h = inImage->getHeight(); int numPixels = w * h; Image *rgbImage = new Image( w, h, 3 ); double *red = rgbImage->getChannel( 0 ); double *green = rgbImage->getChannel( 1 ); double *blue = rgbImage->getChannel( 2 ); double *gray = inImage->getChannel( 0 ); for( int i=0; igetWidth(); int h = inImage->getHeight(); int numPixels = w * h; unsigned char *bytes = new unsigned char[ numPixels ]; double *gray = inImage->getChannel( inChannelNumber ); for( int i=0; igetChannel( 0 ); for( int i=0; igetNumChannels() != 3 ) { printf( "RGBtoHSB requires a 3-channel image as input.\n" ); return NULL; } int w = inRGBImage->getWidth(); int h = inRGBImage->getHeight(); int numPixels = w * h; Image *hsbImage = new Image( w, h, 3 ); double *redChannel = inRGBImage->getChannel( 0 ); double *greenChannel = inRGBImage->getChannel( 1 ); double *blueChannel = inRGBImage->getChannel( 2 ); double *hueChannel = hsbImage->getChannel( 0 ); double *satChannel = hsbImage->getChannel( 1 ); double *brightChannel = hsbImage->getChannel( 2 ); for( int i=0; i g) ? r : g; if (b > cmax) { cmax = b; } int cmin = (r < g) ? r : g; if (b < cmin) { cmin = b; } bright = ( (double)cmax ) / 255.0; if( cmax != 0 ) { sat = ( (double)( cmax - cmin ) ) / ( (double) cmax ); } else { sat = 0; } if( sat == 0 ) { hue = 0; } else { double redc = ( (double)( cmax - r ) ) / ( (double)( cmax - cmin ) ); double greenc = ( (double) ( cmax - g ) ) / ( (double)( cmax - cmin ) ); double bluec = ( (double)( cmax - b ) ) / ( (double)( cmax - cmin ) ); if( r == cmax ) { hue = bluec - greenc; } else if( g == cmax ) { hue = 2.0 + redc - bluec; } else { hue = 4.0 + greenc - redc; } hue = hue / 6.0; if( hue < 0 ) { hue = hue + 1.0; } } hueChannel[i] = hue; satChannel[i] = sat; brightChannel[i] = bright; } return hsbImage; } inline Image *ImageColorConverter::RGBToYIQ( Image *inRGBImage ) { if( inRGBImage->getNumChannels() != 3 ) { printf( "RGBtoYIQ requires a 3-channel image as input.\n" ); return NULL; } Image *yiqImage = coefficientConvert( inRGBImage, 0.299, 0.587, 0.114, 0.596, -0.274, -0.322, 0.212, -0.523, 0.311 ); return yiqImage; } inline Image *ImageColorConverter::YIQToRGB( Image *inYIQImage ) { if( inYIQImage->getNumChannels() != 3 ) { printf( "YIQtoRGB requires a 3-channel image as input.\n" ); return NULL; } Image *rgbImage = coefficientConvert( inYIQImage, 1.0, 0.956, 0.621, 1.0, -0.272, -0.647, 1.0, -1.105, 1.702 ); return rgbImage; } inline Image *ImageColorConverter::RGBToYCbCr( Image *inRGBImage ) { if( inRGBImage->getNumChannels() != 3 ) { printf( "RGBtoYCbCr requires a 3-channel image as input.\n" ); return NULL; } // coefficients taken from the color space faq /* RGB -> YCbCr (with Rec 601-1 specs) Y = 0.2989 * Red + 0.5866 * Green + 0.1145 * Blue Cb = -0.1687 * Red - 0.3312 * Green + 0.5000 * Blue Cr = 0.5000 * Red - 0.4183 * Green - 0.0816 * Blue YCbCr (with Rec 601-1 specs) -> RGB Red = Y + 0.0000 * Cb + 1.4022 * Cr Green = Y - 0.3456 * Cb - 0.7145 * Cr Blue = Y + 1.7710 * Cb + 0.0000 * Cr */ Image *ycbcrImage = coefficientConvert( inRGBImage, 0.2989, 0.5866, 0.1145, -0.1687, -0.3312, 0.5000, 0.5000, -0.4183, -0.0816 ); // adjust the Cb and Cr channels so they are in the range [0,1] int numPixels = ycbcrImage->getWidth() * ycbcrImage->getHeight(); double *cbChannel = ycbcrImage->getChannel( 1 ); double *crChannel = ycbcrImage->getChannel( 2 ); for( int i=0; igetNumChannels() != 3 ) { printf( "YCbCrtoRGB requires a 3-channel image as input.\n" ); return NULL; } // adjust the normalized Cb and Cr channels // so they are in the range [-0.5,0.5] int numPixels = inYCbCrImage->getWidth() * inYCbCrImage->getHeight(); double *cbChannel = inYCbCrImage->getChannel( 1 ); double *crChannel = inYCbCrImage->getChannel( 2 ); for( int i=0; i YCbCr (with Rec 601-1 specs) Y = 0.2989 * Red + 0.5866 * Green + 0.1145 * Blue Cb = -0.1687 * Red - 0.3312 * Green + 0.5000 * Blue Cr = 0.5000 * Red - 0.4183 * Green - 0.0816 * Blue YCbCr (with Rec 601-1 specs) -> RGB Red = Y + 0.0000 * Cb + 1.4022 * Cr Green = Y - 0.3456 * Cb - 0.7145 * Cr Blue = Y + 1.7710 * Cb + 0.0000 * Cr */ Image *rgbImage = coefficientConvert( inYCbCrImage, 1.0, 0.0000, 1.4022, 1.0, -0.3456, -0.7145, 1.0, 1.7710, 0.0000 ); // clip r, g, and b channels to the range [0,1], since // some YCbCr pixel values might map out of this range // (in other words, some YCbCr values map outside of rgb space) for( int c=0; c<3; c++ ) { double *channel = rgbImage->getChannel( c ); for( int p=0; p 1 ) { channel[p] = 1.0; } } } return rgbImage; } inline Image *ImageColorConverter::coefficientConvert( Image *inImage, double inC00, double inC01, double inC02, double inC10, double inC11, double inC12, double inC20, double inC21, double inC22 ) { if( inImage->getNumChannels() != 3 ) { return NULL; } int w = inImage->getWidth(); int h = inImage->getHeight(); int numPixels = w * h; Image *outImage = new Image( w, h, 3 ); double *outChannel0 = outImage->getChannel( 0 ); double *outChannel1 = outImage->getChannel( 1 ); double *outChannel2 = outImage->getChannel( 2 ); double *inChannel0 = inImage->getChannel( 0 ); double *inChannel1 = inImage->getChannel( 1 ); double *inChannel2 = inImage->getChannel( 2 ); for( int i=0; iScreenGraphics. * Adjusts screen resolution and fills screen with black. * * @param inWidth width of desired full screen. * @param inHeight height of desired full screen. */ ScreenGraphics( int inWidth, int inHeight ); /** * Desctructor restores screen to original state. */ ~ScreenGraphics(); /** * Resizes the screen. * * @param inNewWidth the new width. * @param inNewHeight the new height. */ void resize( int inNewWidth, int inNewHeight ); /** * Gets the pixel buffer used by the screen. * * @return a graphics buffer containing a pointer to the screen * pixels. Must be destroyed by caller. */ GraphicBuffer *getScreenBuffer(); /** * Flips a dirty rectangle onto the screen. * * @param inTopLeftX the X coordinate, in pixels, of the top left * point on the rectangle. * @param inTopLeftY the Y coordinate, in pixels, of the top left * point on the rectangle. * @param inWidth the width of the rectangle. * @param inHeight the height of the rectangle. */ void flipDirtyRectangle( int inTopLeftX, int inTopLeftY, int inWidth, int inHeight ); /** * Flips all the pixels stored in the location pointed to by * getScreenBuffer() onto the screen. */ void flipScreen(); /** * Swaps a buffer to the screen. * The next buffer to be filled is returned in * inOutBuffer. * * No guarentee is made about what will be in the next buffer returned. * (On systems that support on-card double buffering, it may even * be a buffer pointing directly into video memory.) * * @param inOutBuffer pointer to the buffer to swap to the screen, * and pointer where the next buffer will be stored. */ void swapBuffers( GraphicBuffer *inOutBuffer ); /** * Determines whether a particular screen setting is available. * * NOTE: Do not call after constructing a ScreenGraphics instance. * * @param inWidth width of desired full screen. * @param inHeight height of desired full screen. * * @return true iff screen setting is available. */ static char isResolutionAvailable( int inWidth, int inHeight ); private: int mWidth; int mHeight; void *mNativeObjectPointer; }; #endif between-6+dfsg1.orig/minorGems/graphics/mac/0000750000175000017500000000000011435543334017545 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/graphics/mac/graphixCommonDefs.h0000640000175000017500000000012511435543334023332 0ustar pabspabs// ALifeGUICommonDefs.h // common definitions for ALifeGui #define MAC_KEY_CODESbetween-6+dfsg1.orig/minorGems/graphics/mac/graphixFramework.cpp0000640000175000017500000001727511435543334023606 0ustar pabspabs/** 32 bit DrawSprockets pluggable framework * * Jason Rohrer, 4-28-99 * * Mods: * Jason Rohrer 11-8-99 Changed to use GraphicBuffer object as screen buffer * Jason Rohrer 12-15-99 Added support for keyboard querying * Jason Rohrer 3-21-2000 Added support for mouse querying * */ #include #include #include // for keyboard events #include #include #include "swapBuffers.h" // interface for swapping buffers #include "getKey.h" // interface for getting key states #include "getMouse.h" // interface for getting mouse state //#include "ALifeGuiRunner.h" #include "GoGUIRunner.h" #include "GraphicBuffer.h" // Constants #define BallWidth 20 #define BallHeight 20 #define BobSize 8 /* Size of text in each ball */ //MT Tutorial #define rWindow 128 // resource ID number for window // Globals Rect windRect; WindowPtr w; DSpContextReference theContext; unsigned long *double_buffer = NULL; // the double buffer unsigned long *screen_buffer = NULL; GraphicBuffer *graphicDoubleBuffer; short bufferHigh = 480; short bufferWide = 640; // prototypes void Initialize(void); void graphixPicker(void); // our mother function, picks effect order, etc. void initVideo(DSpContextReference *theContext); void MyInitAttributes(DSpContextAttributes*); void CleanUp(DSpContextReference theContext); int main() { Initialize(); // setup a window MaxApplZone(); initVideo( &theContext ); // set up and switch video graphixPicker(); CleanUp( theContext); } void graphixPicker() { // our "mother function" // selects which effect to run next // graphix plug-in format: // myGraphix( bufferPtr, bufferHigh, bufferWide, colorBits, numFrames) // function can cll "swapBuffer32" internally whenever it needs the back buffer // sent to the screen. // jcrTorus( double_buffer, 480, 640, 32, 100); // jcrVoxels( double_buffer, 480, 640, 32, 230); // jcrTorus( double_buffer, 480, 640, 32, 50); //jcrBloom( double_buffer, 480, 640, 32, 100); // GraphicBuffer passed in contains all needed info about screen // pass in number of frames to run for //ALifeGuiRunner( *graphicDoubleBuffer, 1000 ); GoGUIRunner( *graphicDoubleBuffer, 0 ); } // Initialize the draw sprockets // set up the video, fade out display, and switch video modes void initVideo(DSpContextReference *theContext) { CGrafPtr backBuffer; PixMapHandle bufferMap; DSpContextAttributes theDesiredAttributes; OSStatus theError; MyInitAttributes(&theDesiredAttributes); theDesiredAttributes.displayWidth = 640; theDesiredAttributes.displayHeight = 480; theDesiredAttributes.colorNeeds = kDSpColorNeeds_Require; theDesiredAttributes.backBufferDepthMask = kDSpDepthMask_32; theDesiredAttributes.displayDepthMask = kDSpDepthMask_32; theDesiredAttributes.backBufferBestDepth = 32; theDesiredAttributes.displayBestDepth = 32; theError = DSpFindBestContext(&theDesiredAttributes, theContext); // add page flipping by video card to request theDesiredAttributes.contextOptions |= kDSpContextOption_PageFlip; //theDesiredAttributes.contextOptions |= kDSpContextOption_DontSyncVBL; // Reserver a display theError = DSpContext_Reserve(*theContext, &theDesiredAttributes); // fade out theError = DSpContext_FadeGammaOut(NULL, NULL); theError = DSpContext_SetState(*theContext, kDSpContextState_Active); ShowCursor(); HideCursor(); // setup global pointers to screen and back buffer theError = DSpContext_GetBackBuffer(*theContext, kDSpBufferKind_Normal, &backBuffer); bufferMap = (PixMapHandle)GetGWorldPixMap(backBuffer); double_buffer = (unsigned long*)(**bufferMap).baseAddr; // create GraphicBuffer object graphicDoubleBuffer = new GraphicBuffer( double_buffer, 640, 480 ); theError = DSpContext_GetFrontBuffer(*theContext, &backBuffer); bufferMap = (PixMapHandle)GetGWorldPixMap(backBuffer); screen_buffer = (unsigned long*)(**bufferMap).baseAddr; theError = DSpContext_FadeGammaIn(NULL, NULL); } // initialize a set of Display attributes to zero void MyInitAttributes (DSpContextAttributes *inAttributes) { if (NULL == inAttributes) DebugStr("\pStimpy! You Idiot!"); inAttributes->frequency = 0; inAttributes->displayWidth = 0; inAttributes->displayHeight = 0; inAttributes->reserved1 = 0; inAttributes->reserved2 = 0; inAttributes->colorNeeds = 0; inAttributes->colorTable = NULL; inAttributes->contextOptions = 0; inAttributes->backBufferDepthMask = 0; inAttributes->displayDepthMask = 0; inAttributes->backBufferBestDepth = 0; inAttributes->displayBestDepth = 0; inAttributes->pageCount = 0; inAttributes->gameMustConfirmSwitch = false; inAttributes->reserved3[0] = 0; inAttributes->reserved3[1] = 0; inAttributes->reserved3[2] = 0; inAttributes->reserved3[3] = 0; } void CleanUp(DSpContextReference theContext) { OSStatus theError; theError = DSpContext_FadeGammaOut(NULL, NULL); /* put the context into the inactive state */ theError = DSpContext_SetState(theContext, kDSpContextState_Inactive); /* fade back in */ theError = DSpContext_FadeGammaIn(NULL, NULL); /* release the context */ theError = DSpContext_Release(theContext); ShowCursor(); } // swap bufferB to the screen (32 bit version) void swapBuffers32( GraphicBuffer &bufferB ) { OSStatus theError; // swap buffers theError = DSpContext_SwapBuffers(theContext, NULL, 0); // get pointer to new back buffer and return it CGrafPtr backBuffer; PixMapHandle bufferMap; theError = DSpContext_GetBackBuffer(theContext, kDSpBufferKind_Normal, &backBuffer); bufferMap = (PixMapHandle)GetGWorldPixMap(backBuffer); // replace the buffer in bufferB with the new double buffer bufferB.setBuffer( (unsigned long*)(**bufferMap).baseAddr ); // memcpy(screen_buffer, bufferPtrB, 4*bufferWide*bufferHigh); } // end of swapBuffers // returns true if key represented by given key code is down char getKeyDown( int vKeyCode ) { unsigned char keyArray [16]; GetKeys( (long *)keyArray ); return ((keyArray[vKeyCode>>3] >> (vKeyCode & 7)) & 1); } // returns true if key is up char getKeyUp( int vKeyCode ) { unsigned char keyArray [16]; GetKeys( (long *)keyArray ); return !((keyArray[vKeyCode>>3] >> (vKeyCode & 7)) & 1); } void getMouse( int *x, int *y ) { Point mousePoint; DSpGetMouse( &mousePoint ); *x = mousePoint.h; *y = mousePoint.v; } void Initialize(void) { WindowPtr mainPtr; OSErr error; SysEnvRec theWorld; // // Test the computer to be sure we can do color. // If not we would crash, which would be bad. // If we can¹t run, just beep and exit. // error = SysEnvirons(1, &theWorld); if (theWorld.hasColorQD == false) { // SysBeep(50); ExitToShell(); // If no color QD, we must leave. } // Initialize all the needed managers. InitGraf(&qd.thePort); // InitFonts(); InitWindows(); InitMenus(); TEInit(); InitDialogs(nil); InitCursor(); // // To make the Random sequences truly random, we need to make the seed start // at a different number. An easy way to do this is to put the current time // and date into the seed. Since it is always incrementing the starting seed // will always be different. Don¹t for each call of Random, or the sequence // will no longer be random. Only needed once, here in the init. // GetDateTime((unsigned long*) &qd.randSeed); // // Make a new window for drawing in, and it must be a color window. // The window is full screen size, made smaller to make it more visible. // mainPtr = GetNewCWindow(rWindow, nil, (WindowPtr) -1); // MW Tutorial windRect = mainPtr->portRect; SetPort(mainPtr); // set window to current graf port TextSize(BobSize); // smaller font for drawing. } between-6+dfsg1.orig/minorGems/graphics/win32/0000750000175000017500000000000011435543334017747 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/graphics/win32/graphixCommonDefs.h0000640000175000017500000000013111435543334023531 0ustar pabspabs// ALifeGUICommonDefs.h // common definitions for ALifeGui #define WINDOWS_KEY_CODESbetween-6+dfsg1.orig/minorGems/graphics/win32/graphixFramework.cpp0000640000175000017500000002651511435543334024005 0ustar pabspabs// 32 bit DDraw pluggable framework // Jason Rohrer, 4-28-99 /** * Mods: * Jason Rohrer 11-8-99 Changed to use GraphicBuffer object as screen buffer * Jason Rohrer 3-21-2000 Added support for mouse querying */ // based on the work of: /* * water ripples effect * -------------------- * anthony greene :: emit * april 1999 */ #define WIN32_LEAN_AND_MEAN // make sure certain headers are included correctly /* includes */ #include // include the standard windows stuff //#include // include the 32 bit stuff //#include // include the multi media stuff // need winmm.lib also #include // include direct draw components #include #include "swapBuffers.h" // interface for swapping buffers #include "getKey.h" // interface for handling keyboard input #include "getMouse.h" // interface for handling mouse input #include "GraphicBuffer.h" //#include "ALifeGuiRunner.h" #include "GoGUIRunner.h" /* defines */ #define WINDOW_CLASS_NAME "WINDOW_CLASS" // this is the name of the window class #define SCREEN_WIDTH 640 // the width of the viewing surface #define SCREEN_HEIGHT 480 // the height of the viewing surface #define SCREEN_BPP 32 // the bits per pixel #define MAX_COLORS 256 // the maximum number of colors /* types */ typedef unsigned char BYTE; typedef unsigned char UCHAR; typedef unsigned short WORD; /* macros */ // these query the keyboard in real-time #define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) #define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1) /* prototypes */ int DD_Init(HWND hwnd); int DD_Shutdown(void); void graphixPicker(void); // our mother function, picks effect order, etc. /* directdraw globals */ LPDIRECTDRAW lpdd = NULL; // dd object LPDIRECTDRAWSURFACE lpddsprimary = NULL; // dd primary surface LPDIRECTDRAWSURFACE lpddsback = NULL; // dd back surface LPDIRECTDRAWPALETTE lpddpal = NULL; // a pointer to the created dd palette PALETTEENTRY color_palette[256]; // holds the shadow palette entries DDSURFACEDESC ddsd; // a direct draw surface description struct DDSCAPS ddscaps; // a direct draw surface capabilities struct HRESULT ddrval; // result back from dd calls HWND main_window_handle = NULL; // used to store the window handle unsigned long *double_buffer = NULL; // the double buffer unsigned long *screen_buffer = NULL; GraphicBuffer *graphicDoubleBuffer; /* globals */ int Height[2][640*480]; int old; int nu; int running = 0; int cycle; /* direct x functions */ int DD_Init(HWND hwnd) { // this function is responsible for initializing direct draw, // it creates a primary surface int index; // looping index // now that the windows portion is complete, start up direct draw if (DirectDrawCreate(NULL,&lpdd,NULL)!=DD_OK) { // shutdown any other dd objects and kill window DD_Shutdown(); return(0); } // now set the coop level to exclusive and set for full screen and mode x if (lpdd->SetCooperativeLevel(hwnd, DDSCL_ALLOWREBOOT | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX)!=DD_OK) { // shutdown any other dd objects and kill window DD_Shutdown(); return(0); } // now set the display mode if (lpdd->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP)!=DD_OK) { // shutdown any other dd objects and kill window DD_Shutdown(); return(0); } // Create the primary surface memset(&ddsd,0,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; if (lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL)!=DD_OK) { // shutdown any other dd objects and kill window DD_Shutdown(); return(0); } // end if // allocate memory for the double buffer if ((double_buffer = (unsigned long *)malloc(SCREEN_WIDTH*SCREEN_HEIGHT*4))==NULL) return(0); // create GraphicBuffer object graphicDoubleBuffer = new GraphicBuffer( double_buffer, 640, 480 ); // create the palette and attach it to the primary surface // clear all the palette entries to RGB 0,0,0 memset(color_palette,0,256*sizeof(PALETTEENTRY)); // set all of the flags to the correct value int c=0; for (index=0; index<256; index++) { // create the GRAY/RED/GREEN/BLUE palette, 64 shades of each if (index < 64) { color_palette[index].peRed = index; color_palette[index].peGreen = 0; color_palette[index].peBlue = 0; } else if (index < 128) { color_palette[index].peRed = index; color_palette[index].peGreen = 0; color_palette[index].peBlue = 0; } else if (index < 192) { color_palette[index].peRed = index; color_palette[index].peGreen = c; color_palette[index].peBlue = c; c++; } else if (index < 256) { color_palette[index].peRed = index; color_palette[index].peGreen = c; color_palette[index].peBlue = c; c++; } // set the no collapse flag color_palette[index].peFlags = PC_NOCOLLAPSE; } // now create the palette object, note that it is a member of the dd object itself if (lpdd->CreatePalette((DDPCAPS_8BIT | DDPCAPS_INITIALIZE),color_palette,&lpddpal,NULL)!=DD_OK) { // shutdown any other dd objects and kill window DD_Shutdown(); return(0); } // now attach the palette to the primary surface lpddsprimary->SetPalette(lpddpal); // return success if we got this far return(1); } int DD_Shutdown(void) { // this function tests for dd components that have been created // and releases them back to the operating system // test if the dd object exists if (lpdd) { // test if there is a primary surface if(lpddsprimary) { // release the memory and set pointer to NULL lpddsprimary->Release(); lpddsprimary = NULL; } // now release the dd object itself lpdd->Release(); lpdd = NULL; // free double buffer if (double_buffer!=NULL) free(double_buffer); // return success return(1); } else return(0); } /* windows callback fucntion */ LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { // this is the main message handler of the system HDC hdc; // handle to graphics context PAINTSTRUCT ps; // used to hold the paint info // what is the message.. switch(msg) { case WM_CREATE: { // do windows inits here return(0); } break; case WM_PAINT: { // this message occurs when your window needs repainting hdc = BeginPaint(hwnd,&ps); EndPaint((struct HWND__ *)hdc,&ps); return(0); } break; case WM_DESTROY: { // this message is sent when your window is destroyed PostQuitMessage(0); return(0); } break; case WM_MOUSEMOVE: { // extract x,y /* int mouse_x = (int)LOWORD(lparam); int mouse_y = (int)HIWORD(lparam); Height[old][mouse_y*640+mouse_x] = 300; */ return(0); } break; default:break; } // let windows process any messages that we didn't take care of return (DefWindowProc(hwnd, msg, wparam, lparam)); } int WINAPI WinMain( HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) { WNDCLASSEX winclass; // this holds the windows class info HWND hwnd; // this holds the handle of our new window MSG msg; // this holds a generic message // first fill in the window class stucture winclass.cbSize = sizeof(WNDCLASSEX); winclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW; winclass.lpfnWndProc = WindowProc; winclass.cbClsExtra = 0; winclass.cbWndExtra = 0; winclass.hInstance = hinstance; winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); winclass.hCursor = LoadCursor(NULL, IDC_ARROW); winclass.hbrBackground = (struct HBRUSH__ *)GetStockObject(BLACK_BRUSH); winclass.lpszMenuName = NULL; winclass.lpszClassName = WINDOW_CLASS_NAME; // register the window class if (!RegisterClassEx(&winclass)) return(0); // create the window if (!(hwnd = CreateWindowEx(WS_EX_TOPMOST, WINDOW_CLASS_NAME, // class "water", // title WS_VISIBLE | WS_POPUP, 0,0, // x,y GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, // parent NULL, // menu hinstance, // instance NULL))) // creation parms return(0); // hide the mouse cursor ShowCursor(0); // save the window handle main_window_handle = hwnd; // initialize direct draw if (!DD_Init(hwnd)) { DestroyWindow(hwnd); return(0); } // peek at the message once just to make them happy PeekMessage(&msg,NULL,0,0,PM_REMOVE); // do it once, then leave graphixPicker(); // picks which effects to run. // afterwards, end!!! // shut down direct draw DD_Shutdown(); // return to Windows return(msg.wParam); } void graphixPicker() { // our "mother function" // selects which effect to run next // graphix plug-in format: // myGraphix( bufferPtr, bufferHigh, bufferWide, colorBits, numFrames) // function can cll "swapBuffer32" internally whenever it needs the back buffer // sent to the screen. // jcrTorus( double_buffer, 480, 640, 32, 100); // jcrVoxels( double_buffer, 480, 640, 32, 230); // jcrTorus( double_buffer, 480, 640, 32, 50); // jcrBloom( double_buffer, 480, 640, 32, 100); //ALifeGuiRunner( *graphicDoubleBuffer, 200 ); GoGUIRunner( *graphicDoubleBuffer, 0 ); } char getKeyDown( int vKeyCode ) { return ((GetAsyncKeyState(vKeyCode) & 0x8000) ? true : false); } char getKeyUp( int vKeyCode ) { return ((GetAsyncKeyState(vKeyCode) & 0x8000) ? false : true); } void getMouse( int *x, int *y ) { POINT p; GetCursorPos( &p ); *x = p.x; *y = p.y; } /// CODE FOR SWAPPING BUFFERES BELOW THIS POINT....... // swap bufferB to the screen (32 bit version) void swapBuffers32( GraphicBuffer &bufferB ) { unsigned long *primary_buffer = NULL, // used to draw *dest_ptr = NULL, // used in line by line copy *src_ptr = NULL; // " " short bufferHigh = 480; short bufferWide = 640; // copy the double buffer into the primary buffer memset(&ddsd,0,sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); // lock the primary surface lpddsprimary->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL); // get video pointer to primary surfce primary_buffer = (unsigned long *)ddsd.lpSurface; // test if memory is linear if (ddsd.lPitch == 640*4) { // copy memory from double buffer to primary buffer memcpy(primary_buffer, double_buffer, 640*480*4); } else { // non-linear // make copy of source and destination addresses dest_ptr = primary_buffer; src_ptr = double_buffer; // memory is non-linear, copy line by line for (int y=0; yUnlock(primary_buffer); } // end of swapBuffers between-6+dfsg1.orig/minorGems/graphics/loadfile.h0000640000175000017500000000025311435543334020736 0ustar pabspabsvoid loadFile( const char* fileName, long sizeInBytes, unsigned char* byteDestPtr); void loadRawFile( const char* fileName, long sizeInBytes, unsigned char* byteDestPtr);between-6+dfsg1.orig/minorGems/graphics/test/0000750000175000017500000000000011435543334017764 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/graphics/test/tgaConverter.cpp0000640000175000017500000001002011435543334023125 0ustar pabspabs/* * Modification History * * 2001-September-24 Jason Rohrer * Created. */ #include "minorGems/graphics/Image.h" #include "minorGems/graphics/ImageColorConverter.h" #include "minorGems/graphics/converters/TGAImageConverter.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/FileInputStream.h" #include "minorGems/io/file/FileOutputStream.h" #include #include #include void usage( char *inAppName ); Image *loadTGAImage( char *inFileName ); void writeTGAImage( char *inFileName, Image *inImage ); // normalizes an image into the pixel range [0,1] if some // pixels are out of range void normalizeImage( Image *inImage ); // a test program that converts a tga image between // parameterizable color formats int main( char inNumArgs, char **inArgs ) { if( inNumArgs != 5 ) { usage( inArgs[0] ); } Image *inImage = loadTGAImage( inArgs[1] ); Image *outImage; // convert inImage to outImage based on the color space strings if( !strcmp( inArgs[3], "rgb" ) ) { if( !strcmp( inArgs[4], "yiq" ) ) { outImage = ImageColorConverter::RGBToYIQ( inImage ); } if( !strcmp( inArgs[4], "ycbcr" ) ) { outImage = ImageColorConverter::RGBToYCbCr( inImage ); } } if( !strcmp( inArgs[3], "yiq" ) ) { if( !strcmp( inArgs[4], "rgb" ) ) { outImage = ImageColorConverter::YIQToRGB( inImage ); } if( !strcmp( inArgs[4], "ycbcr" ) ) { Image *tempImage = ImageColorConverter::YIQToRGB( inImage ); outImage = ImageColorConverter::RGBToYCbCr( tempImage ); delete tempImage; } } if( !strcmp( inArgs[3], "ycbcr" ) ) { if( !strcmp( inArgs[4], "rgb" ) ) { outImage = ImageColorConverter::YCbCrToRGB( inImage ); } if( !strcmp( inArgs[4], "yiq" ) ) { Image *tempImage = ImageColorConverter::YCbCrToRGB( inImage ); outImage = ImageColorConverter::RGBToYIQ( tempImage ); delete tempImage; } } writeTGAImage( inArgs[2], outImage ); delete inImage; delete outImage; return 0; } void usage( char *inAppName ) { printf( "Usage:\n" ); printf( "\t%s in_image_tga out_image_tga in_format out_format\n", inAppName ); printf( "Example:\n" ); printf( "\t%s testRGB.tga testYIQ.bmp rgb yiq\n", inAppName ); printf( "The following color formats are supported:\n" ); printf( "\trgb, yiq, ycbcr\n" ); exit( 1 ); } void normalizeImage( Image *inImage ) { // now normalize the image so that pixels are in the range [0,1] int numPixels = inImage->getWidth() * inImage->getHeight(); int numChannels = inImage->getNumChannels(); double minValue = 1000.0; double maxValue = -1000.0; int c; // search for min and max values for( c=0; cgetChannel( c ); for( int p=0; p maxValue ) { maxValue = channel[p]; } } } double diff = maxValue - minValue; if( minValue >= 0 && diff + minValue <= 1 ) { // no need to normalize, as values are already // in range return; } double scale = 1.0 / diff; // now normalize all pixels for( c=0; cgetChannel( c ); for( int p=0; pdeformatImage( imageStream ); delete imageFile; delete imageStream; delete converter; return returnImage; } void writeTGAImage( char *inFileName, Image *inImage ) { File *imageFile = new File( NULL, inFileName, strlen( inFileName ) ); FileOutputStream *imageStream = new FileOutputStream( imageFile ); TGAImageConverter *converter = new TGAImageConverter(); converter->formatImage( inImage, imageStream ); delete imageFile; delete imageStream; delete converter; } between-6+dfsg1.orig/minorGems/graphics/test/yiq2rgb.cpp0000640000175000017500000000622211435543334022052 0ustar pabspabs/* * Modification History * * 2001-September-20 Jason Rohrer * Created. * Changed so that images are normalized to [0,1] before * being output. */ #include "minorGems/graphics/Image.h" #include "minorGems/graphics/ImageColorConverter.h" #include "minorGems/graphics/converters/BMPImageConverter.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/FileInputStream.h" #include "minorGems/io/file/FileOutputStream.h" #include #include void usage( char *inAppName ); Image *loadBMPImage( char *inFileName ); void writeBMPImage( char *inFileName, Image *inImage ); // normalizes an image into the pixel range [0,1] if some // pixels are out of range void normalizeImage( Image *inImage ); // a test program that converts an rgb BMP to a yiq BMP int main( char inNumArgs, char **inArgs ) { if( inNumArgs != 3 ) { usage( inArgs[0] ); } Image *yiqImage = loadBMPImage( inArgs[1] ); if( yiqImage == NULL ) { printf( "Reading image from file %s failed\n", inArgs[1] ); usage( inArgs[0] ); } Image *rgbImage = ImageColorConverter::YIQToRGB( yiqImage ); normalizeImage( rgbImage ); writeBMPImage( inArgs[2], rgbImage ); delete rgbImage; delete yiqImage; return 0; } void usage( char *inAppName ) { printf( "Usage:\n" ); printf( "\t%s yiq_image_bmp rgb_image_bmp\n", inAppName ); printf( "Example:\n" ); printf( "\t%s testYIQ.bmp testRGB.bmp\n", inAppName ); exit( 1 ); } void normalizeImage( Image *inImage ) { // now normalize the image so that pixels are in the range [0,1] int numPixels = inImage->getWidth() * inImage->getHeight(); int numChannels = inImage->getNumChannels(); double minValue = 1000.0; double maxValue = -1000.0; int c; // search for min and max values for( c=0; cgetChannel( c ); for( int p=0; p maxValue ) { maxValue = channel[p]; } } } double diff = maxValue - minValue; if( minValue >= 0 && diff + minValue <= 1 ) { // no need to normalize, as values are already // in range return; } double scale = 1.0 / diff; // now normalize all pixels for( c=0; cgetChannel( c ); for( int p=0; pdeformatImage( imageStream ); delete imageFile; delete imageStream; delete converter; return returnImage; } void writeBMPImage( char *inFileName, Image *inImage ) { File *imageFile = new File( NULL, inFileName, strlen( inFileName ) ); FileOutputStream *imageStream = new FileOutputStream( imageFile ); BMPImageConverter *converter = new BMPImageConverter(); converter->formatImage( inImage, imageStream ); delete imageFile; delete imageStream; delete converter; } between-6+dfsg1.orig/minorGems/graphics/test/rgb2yiq.cpp0000640000175000017500000000615711435543334022061 0ustar pabspabs/* * Modification History * * 2001-September-19 Jason Rohrer * Created. * * 2001-September-20 Jason Rohrer * Finished initial implementation. * Changed so that images are normalized to [0,1] before * being output. */ #include "minorGems/graphics/Image.h" #include "minorGems/graphics/ImageColorConverter.h" #include "minorGems/graphics/converters/BMPImageConverter.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/FileInputStream.h" #include "minorGems/io/file/FileOutputStream.h" #include #include void usage( char *inAppName ); Image *loadBMPImage( char *inFileName ); void writeBMPImage( char *inFileName, Image *inImage ); // normalizes an image into the pixel range [0,1] if some // pixels are out of range void normalizeImage( Image *inImage ); // a test program that converts an rgb BMP to a yiq BMP int main( char inNumArgs, char **inArgs ) { if( inNumArgs != 3 ) { usage( inArgs[0] ); } Image *rgbImage = loadBMPImage( inArgs[1] ); Image *yiqImage = ImageColorConverter::RGBToYIQ( rgbImage ); normalizeImage( yiqImage ); writeBMPImage( inArgs[2], yiqImage ); delete rgbImage; delete yiqImage; return 0; } void usage( char *inAppName ) { printf( "Usage:\n" ); printf( "\t%s rgb_image_bmp yiq_image_bmp\n", inAppName ); printf( "Example:\n" ); printf( "\t%s testRGB.bmp testYIQ.bmp\n", inAppName ); exit( 1 ); } void normalizeImage( Image *inImage ) { // now normalize the image so that pixels are in the range [0,1] int numPixels = inImage->getWidth() * inImage->getHeight(); int numChannels = inImage->getNumChannels(); double minValue = 1000.0; double maxValue = -1000.0; int c; // search for min and max values for( c=0; cgetChannel( c ); for( int p=0; p maxValue ) { maxValue = channel[p]; } } } double diff = maxValue - minValue; if( minValue >= 0 && diff + minValue <= 1 ) { // no need to normalize, as values are already // in range return; } double scale = 1.0 / diff; // now normalize all pixels for( c=0; cgetChannel( c ); for( int p=0; pdeformatImage( imageStream ); delete imageFile; delete imageStream; delete converter; return returnImage; } void writeBMPImage( char *inFileName, Image *inImage ) { File *imageFile = new File( NULL, inFileName, strlen( inFileName ) ); FileOutputStream *imageStream = new FileOutputStream( imageFile ); BMPImageConverter *converter = new BMPImageConverter(); converter->formatImage( inImage, imageStream ); delete imageFile; delete imageStream; delete converter; } between-6+dfsg1.orig/minorGems/graphics/test/tgaConverterCompile0000750000175000017500000000014111435543334023662 0ustar pabspabsg++ -g -o tgaConverter -I../../.. tgaConverter.cpp ../../../minorGems/io/file/linux/PathLinux.cppbetween-6+dfsg1.orig/minorGems/graphics/test/rgb2yiqCompile0000750000175000017500000000012411435543334022577 0ustar pabspabsg++ -o rgb2yiq -I../../.. rgb2yiq.cpp ../../../minorGems/io/file/linux/PathLinux.cppbetween-6+dfsg1.orig/minorGems/graphics/test/yiq2rgbCompile0000750000175000017500000000012711435543334022602 0ustar pabspabsg++ -g -o yiq2rgb -I../../.. yiq2rgb.cpp ../../../minorGems/io/file/linux/PathLinux.cppbetween-6+dfsg1.orig/minorGems/numtest.cpp0000640000175000017500000000135511435543336017417 0ustar pabspabs/* * Modification History * * 2001-February-3 Jason Rohrer * Created. * * 2001-February-4 Jason Rohrer * Fixed a bug that made this test not compatible with TypeIO. * Fixed comment. */ #include // function for testing how doubles are stored /* * The output from a big-endian linux is as follows: * * size of double = 8 * byte 0 = 63 * byte 1 = 255 * byte 2 = 189 * byte 3 = 137 * byte 4 = 176 * byte 5 = 126 * byte 6 = 158 * byte 7 = 168 * */ int main() { printf( "size of double = %d\n", sizeof( double ) ); double x = 1.983773889; unsigned char *doubleBuffer = (unsigned char*)( &x ); for( int i=0; i<8; i++ ) { printf( "byte %d = %d\n", i, doubleBuffer[i] ); } return 0; } between-6+dfsg1.orig/minorGems/.hgignore0000640000175000017500000000004711435543333017011 0ustar pabspabs# use glob syntax. syntax: glob *.o *~between-6+dfsg1.orig/minorGems/system/0000750000175000017500000000000011435543337016534 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/system/semaphoreTest.cpp0000640000175000017500000000366411435543337022075 0ustar pabspabs/* * Modification History * * 2001-January-11 Jason Rohrer * Created. * * 2001-January-27 Jason Rohrer * Made printing in threads thread-safe. */ #include "BinarySemaphore.h" #include "Semaphore.h" #include "Thread.h" #include "ThreadSafePrinter.h" #include /** * Thread that waits on a semaphore. * * @author Jason Rohrer */ class WaitingThread : public Thread { public: WaitingThread( int inID, Semaphore *inSemaphore ); // override the run method from PThread void run(); private: Semaphore *mSemaphore; int mID; }; inline WaitingThread::WaitingThread( int inID, Semaphore *inSemaphore ) : mID( inID ), mSemaphore( inSemaphore ) { } inline void WaitingThread::run() { for( int i=0; i<10; i++ ) { ThreadSafePrinter::printf( "%d waiting for signal %d...\n", mID, i ); mSemaphore->wait(); ThreadSafePrinter::printf( "%d received signal %d.\n", mID, i ); } } /** * Thread that signals on a semaphore. * * @author Jason Rohrer */ class SignalingThread : public Thread { public: SignalingThread( Semaphore *inSemaphore ); // override the run method from PThread void run(); private: Semaphore *mSemaphore; }; inline SignalingThread::SignalingThread( Semaphore *inSemaphore ) : mSemaphore( inSemaphore ) { } inline void SignalingThread::run() { for( int i=0; i<5; i++ ) { sleep( 5000 ); ThreadSafePrinter::printf( "Signaling 20 times\n" ); for( int j=0; j<20; j++ ) { mSemaphore->signal(); } } } int main() { int i; Semaphore *semph = new Semaphore(); SignalingThread *threadS = new SignalingThread( semph ); WaitingThread **threadW = new WaitingThread*[10]; for( i=0; i<10; i++ ) { threadW[i] = new WaitingThread( i, semph ); threadW[i]->start(); } threadS->start(); for( i=0; i<10; i++ ) { threadW[i]->join(); delete threadW[i]; } threadS->join(); delete semph; delete threadS; delete [] threadW; return 0; } between-6+dfsg1.orig/minorGems/system/unix/0000750000175000017500000000000011435543337017517 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/system/unix/LauncherUnix.cpp0000640000175000017500000000077311435543337022640 0ustar pabspabs/* * Modification History * * 2003-January-10 Jason Rohrer * Created. */ #include "minorGems/system/Launcher.h" #include #include void Launcher::launchCommand( char *inCommandName, char **inArguments ) { int forkValue = fork(); if( forkValue == 0 ) { // we're in child process, so exec command execvp( inCommandName, inArguments ); // we'll never return from this call } } between-6+dfsg1.orig/minorGems/system/unix/TimeUnix.cpp0000640000175000017500000000123411435543337021766 0ustar pabspabs/* * Modification History * * 2001-October-29 Jason Rohrer * Created. * * 2002-March-13 Jason Rohrer * Added include of time.h so that FreeBSD compile will work. * Changed to use newer gettimeofday that should work on all unix platforms. * Fixed a conversion bug. */ #include "minorGems/system/Time.h" #include #include #include #include void Time::getCurrentTime( unsigned long *outSeconds, unsigned long *outMilliseconds ) { struct timeval currentTime; gettimeofday( ¤tTime, NULL ); *outMilliseconds = currentTime.tv_usec / 1000; *outSeconds = currentTime.tv_sec; } between-6+dfsg1.orig/minorGems/system/endian.h0000640000175000017500000000317111435543337020146 0ustar pabspabs/* * Modification History * * 2002-May-25 Jason Rohrer * Created. * * 2004-January-12 Jason Rohrer * Added support for metrowerks win32 compiler. * * 2009-April-3 Jason Rohrer * OpenBSD support. */ #include "minorGems/common.h" /** * Include this file to define __BYTE_ORDER * * After this has been included, __BYTE_ORDER will be either * __LITTLE_ENDIAN or * __BIG_ENDIAN */ #ifdef __FreeBSD__ #include #elif defined(__NetBSD__) #include #elif defined(__OpenBSD__) #include #include // default BSD case #elif defined(BSD) #include #elif defined(SOLARIS) // Code for Solaris defs adapted from: // MD5 message-digest algorithm. // by Colin Plumb in 1993, no copyright is claimed. //each solaris is different -- this won't work on 2.6 or 2.7 # include #define __LITTLE_ENDIAN 1234 #define __BIG_ENDIAN 4321 #ifdef _LITTLE_ENDIAN #define __BYTE_ORDER __LITTLE_ENDIAN #else // default to big endian #define __BYTE_ORDER __BIG_ENDIAN #endif // end solaris case #elif defined(WIN_32) || \ ( defined(__MWERKS__) && defined(__INTEL__) ) // windows case #define __LITTLE_ENDIAN 1234 #define __BYTE_ORDER __LITTLE_ENDIAN // end windows case #else // linux case #include // end linux case #endif // end of all system-specific cases // BSD calls it BYTE_ORDER, linux calls it __BYTE_ORDER #ifndef __BYTE_ORDER #define __BYTE_ORDER BYTE_ORDER #endif #ifndef __LITTLE_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #endif #ifndef __BIG_ENDIAN #define __BIG_ENDIAN BIG_ENDIAN #endif between-6+dfsg1.orig/minorGems/system/BinarySemaphore.h0000640000175000017500000000331311435543337021776 0ustar pabspabs/* * Modification History * * 2001-January-11 Jason Rohrer * Created. * * 2001-January-27 Jason Rohrer * Fixed a bug in the precompiler directives. * * 2003-August-26 Jason Rohrer * Added support for timeouts on wait. */ #include "minorGems/common.h" #ifndef BINARY_SEMAPHORE_CLASS_INCLUDED #define BINARY_SEMAPHORE_CLASS_INCLUDED #include "MutexLock.h" /** * Binary semaphore class. Semaphore starts out with a value of 0. * * Note: Implementation for the functions defined here is provided * separately for each platform (in the mac/ linux/ and win32/ * subdirectories). * * @author Jason Rohrer */ class BinarySemaphore { public: /** * Constructs a binary semaphore. */ BinarySemaphore(); ~BinarySemaphore(); /** * Blocks on this semaphore until signal() is called by another thread. * Note that if signal() has already been called before wait() is * called, then this call will return immediately, though the semaphore * is reset to 0 by this call. * * @param inTimeoutInMilliseconds the maximum time to wait in * milliseconds, or -1 to wait forever. Defaults to -1. * * @return 1 if the semaphore was signaled, or 0 if it timed out. */ int wait( int inTimeoutInMilliseconds = -1 ); /** * Signals the semaphore, allowing a waiting thread to return from * its call to wait(). (The semaphore is set to 1 by this call if * no thread is waiting on the semaphore currently.) */ void signal(); private: // starts at 0 int mSemaphoreValue; /** * Used by platform-specific implementations. */ void *mNativeObjectPointerA; void *mNativeObjectPointerB; }; #endif between-6+dfsg1.orig/minorGems/system/Launcher.h0000640000175000017500000000163011435543337020447 0ustar pabspabs/* * Modification History * * 2003-January-10 Jason Rohrer * Created. */ #include "minorGems/common.h" #ifndef LAUNCHER_INCLUDED #define LAUNCHER_INCLUDED /** * Interface for launching processes. * * @author Jason Rohrer */ class Launcher { public: /** * Launches a command in a new process. * * @param inCommandName the name of the command to launch. * Must be destroyed by caller if non-const. * @param inArguments an array of argument strings for the command. * This array must be terminated by a NULL pointer. * Note that by convention, the first argument should be the * command name. * Must be destroyed by caller. */ static void launchCommand( char *inCommandName, char **inArguments ); }; #endif between-6+dfsg1.orig/minorGems/system/Time.h0000640000175000017500000000444311435543337017611 0ustar pabspabs/* * Modification History * * 2001-October-29 Jason Rohrer * Created. * * 2004-October-14 Jason Rohrer * Fixed sign bug. * * 2005-February-10 Jason Rohrer * Added function to get time in floating point format. */ #include "minorGems/common.h" #ifndef TIME_INCLUDED #define TIME_INCLUDED /** * Interface for platform-independent, high-resolution time access. * * @author Jason Rohrer */ class Time { public: /** * Gets the current time in seconds and milliseconds. * * No guarentee about when absolute 0 of this time * scale is for particular systems. * * @param outSeconds pointer to where the time in seconds * will be returned. * @param outMilliseconds pointer to where the extra * milliseconds will be returned. Value returned is in [0,999]. */ static void getCurrentTime( unsigned long *outSeconds, unsigned long *outMilliseconds ); /** * Gets the current time in fractional (double) seconds. * * @return the current time in seconds. */ static double getCurrentTime(); /** * Gets the number of milliseconds that have passed * since a time in seconds and milliseconds. * * @param inSeconds the start time, in seconds. * @param inMilliseconds the start time's additional milliseconds. * * @return the number of milliseconds that have passed * since inSeconds:inMilliseconds. May overflow if * more than 49 days have passed (assuming 32-bit longs). */ static unsigned long getMillisecondsSince( unsigned long inSeconds, unsigned long inMilliseconds ); }; inline double Time::getCurrentTime() { unsigned long currentTimeS; unsigned long currentTimeMS; getCurrentTime( ¤tTimeS, ¤tTimeMS ); return currentTimeS + currentTimeMS / 1000.0; } inline unsigned long Time::getMillisecondsSince( unsigned long inSeconds, unsigned long inMilliseconds ) { unsigned long currentTimeS; unsigned long currentTimeMS; getCurrentTime( ¤tTimeS, ¤tTimeMS ); unsigned long deltaS = ( currentTimeS - inSeconds ); long deltaMS = ( (long)currentTimeMS - (long)inMilliseconds ); // carry, if needed if( deltaMS < 0 ) { deltaS--; deltaMS += 1000; } return 1000 * deltaS + deltaMS; } #endif between-6+dfsg1.orig/minorGems/system/Semaphore.h0000640000175000017500000001023311435543337020630 0ustar pabspabs/* * Modification History * * 2001-January-11 Jason Rohrer * Created. * * 2001-January-11 Jason Rohrer * Added a willBlock() function. * * 2001-February-24 Jason Rohrer * Fixed incorrect delete usage. * * 2002-February-11 Jason Rohrer * Fixed a mistake in the signal() comment. * * 2003-August-26 Jason Rohrer * Added support for timeouts on wait. * * 2003-December-28 Jason Rohrer * Fixed a bug in semaphore value when we timeout on wait. * * 2004-January-9 Jason Rohrer * Fixed a preprocessor error. */ #include "minorGems/common.h" #ifndef SEMAPHORE_CLASS_INCLUDED #define SEMAPHORE_CLASS_INCLUDED #include "MutexLock.h" #include "BinarySemaphore.h" /** * General semaphore with an unbounded value. * * This class uses BinarySemaphores to implement general semaphores, * so it relies on platform-specific BinarySemaphore implementations, * but this class itself is platform-independent. * * @author Jason Rohrer */ class Semaphore { public: /** * Constructs a semaphore. * * @param inStartingValue the starting value for this semaphore. * Defaults to 0 if unspecified. */ Semaphore( int inStartingValue = 0 ); ~Semaphore(); /** * If this semaphore's current value is 0, then this call blocks * on this semaphore until signal() is called by another thread. * If this semaphore's value is >0, then it is decremented by this * call. * * @param inTimeoutInMilliseconds the maximum time to wait in * milliseconds, or -1 to wait forever. Defaults to -1. * * @return 1 if the semaphore was signaled, or 0 if it timed out. */ int wait( int inTimeoutInMilliseconds = -1 ); /** * If a thread is waiting on this semaphore, then the thread * becomes unblocked. * If no thread is waiting, then the semaphore is incremented. */ void signal(); /** * Returns true if a call to wait would have blocked. */ char willBlock(); private: // starts at 0 int mSemaphoreValue; // mutex semaphore starts at 1 BinarySemaphore *mMutexSemaphore; // blocking semaphore starts at 0 BinarySemaphore *mBlockingSemaphore; }; inline Semaphore::Semaphore( int inStartingValue ) : mSemaphoreValue( inStartingValue ), mMutexSemaphore( new BinarySemaphore() ), mBlockingSemaphore( new BinarySemaphore() ) { // increment the mutex semaphore to 1 mMutexSemaphore->signal(); } inline Semaphore::~Semaphore() { delete mMutexSemaphore; delete mBlockingSemaphore; } inline int Semaphore::wait( int inTimeoutInMilliseconds ) { int returnValue; // this implementation copied from _Operating System Concepts_, p. 172 // lock the mutex mMutexSemaphore->wait(); // decrement the semaphore mSemaphoreValue--; if( mSemaphoreValue < 0 ) { // we should block // release the mutex mMutexSemaphore->signal(); // block returnValue = mBlockingSemaphore->wait( inTimeoutInMilliseconds ); if( returnValue != 1 ) { // timed out // increment the semaphore, since we never got signaled // lock the mutex mMutexSemaphore->wait(); mSemaphoreValue++; // we will unlock the mutex below } } else { returnValue = 1; } // release the mutex // ( if we were signaled, then the signaller left the mutex locked ) // ( if we timed out, then we re-locked the mutex above ) mMutexSemaphore->signal(); return returnValue; } inline char Semaphore::willBlock() { char returnValue = false; // lock the mutex mMutexSemaphore->wait(); // check if we will block if( mSemaphoreValue <= 0 ) { returnValue = true; } // release the mutex mMutexSemaphore->signal(); return returnValue; } inline void Semaphore::signal() { // lock the mutex mMutexSemaphore->wait(); // increment the semaphore mSemaphoreValue++; if( mSemaphoreValue <= 0 ) { // we need to wake up a waiting thread mBlockingSemaphore->signal(); // let the waiting thread unlock the mutex } else { // no threads are waiting, so we need to unlock the mutex mMutexSemaphore->signal(); } } #endif between-6+dfsg1.orig/minorGems/system/MutexLock.h0000640000175000017500000000207311435543337020623 0ustar pabspabs/* * Modification History * * 2000-December-13 Jason Rohrer * Created. * * 2002-March-29 Jason Rohrer * Added Fortify inclusion. * * 2002-October-18 Jason Rohrer * Moved common include out of header and into platform-specific cpp files, * since MemoryTrack uses a mutex lock. */ #ifndef MUTEX_LOCK_CLASS_INCLUDED #define MUTEX_LOCK_CLASS_INCLUDED #ifdef FORTIFY #include "minorGems/util/development/fortify/fortify.h" #endif /** * Mutex lock class. * * Note: Implementation for the functions defined here is provided * separately for each platform (in the mac/ linux/ and win32/ * subdirectories). * * @author Jason Rohrer */ class MutexLock { public: /** * Constructs a mutex lock; */ MutexLock(); ~MutexLock(); /** * Locks the mutex. Blocks until mutex available if it's * already locked by another thread. */ void lock(); /** * Unlocks the mutex. */ void unlock(); private: /** * Used by platform-specific implementations. */ void *mNativeObjectPointer; }; #endif between-6+dfsg1.orig/minorGems/system/FinishedSignalThread.cpp0000640000175000017500000000203411435543337023257 0ustar pabspabs/* * Modification History * * 2002-March-9 Jason Rohrer * Created. * * 2002-March-11 Jason Rohrer * Changed so that destructor joins thread. * * 2002-April-4 Jason Rohrer * Changed name of lock to avoid confusion with subclass-provided locks. * * 2002-August-5 Jason Rohrer * Fixed member initialization order to match declaration order. * * 2004-April-1 Jason Rohrer * Moved from konspire2b into minorGems. * Changed so that destructor does not join the thread. */ #include "FinishedSignalThread.h" #include FinishedSignalThread::FinishedSignalThread() : mFinishedLock( new MutexLock() ), mFinished( false ) { } FinishedSignalThread::~FinishedSignalThread() { delete mFinishedLock; } char FinishedSignalThread::isFinished() { mFinishedLock->lock(); char finished = mFinished; mFinishedLock->unlock(); return finished; } void FinishedSignalThread::setFinished() { mFinishedLock->lock(); mFinished = true; mFinishedLock->unlock(); } between-6+dfsg1.orig/minorGems/system/FinishedSignalThreadManager.cpp0000640000175000017500000000461511435543337024561 0ustar pabspabs/* * Modification History * * 2004-November-9 Jason Rohrer * Created. * Modified from MUTE's ChannelReceivingThreadManager. * * 2005-January-9 Jason Rohrer * Changed to sleep on a semaphore to allow sleep to be interrupted. */ #include "minorGems/system/FinishedSignalThreadManager.h" FinishedSignalThreadManager::FinishedSignalThreadManager() : mLock( new MutexLock() ), mThreadVector( new SimpleVector() ), mStopSignal( false ), mSleepSemaphore( new BinarySemaphore() ) { this->start(); } FinishedSignalThreadManager::~FinishedSignalThreadManager() { mLock->lock(); mStopSignal = true; mLock->unlock(); // signal the sleeping semaphore to wake up the thread mSleepSemaphore->signal(); this->join(); mLock->lock(); // destroy all remaining threads int numThreads = mThreadVector->size(); for( int i=0; igetElement( i ) ); } delete mThreadVector; mLock->unlock(); delete mLock; delete mSleepSemaphore; } void FinishedSignalThreadManager::addThread( FinishedSignalThread *inThread ) { mLock->lock(); mThreadVector->push_back( inThread ); mLock->unlock(); } void FinishedSignalThreadManager::run() { char stopped; mLock->lock(); stopped = mStopSignal; mLock->unlock(); while( !stopped ) { // wait for 10 seconds int wasSignaled = mSleepSemaphore->wait( 10000 ); if( wasSignaled == 1 ) { // signaled... we should stop return; } char foundFinished = true; while( foundFinished ) { foundFinished = false; mLock->lock(); int numThreads = mThreadVector->size(); for( int i=0; igetElement( i ) ); if( currentThread->isFinished() ) { delete currentThread; mThreadVector->deleteElement( i ); foundFinished = true; } } mLock->unlock(); } mLock->lock(); stopped = mStopSignal; mLock->unlock(); } } between-6+dfsg1.orig/minorGems/system/TestThread.h0000640000175000017500000000252111435543337020755 0ustar pabspabs/* * Modification History * * 2000-December-13 Jason Rohrer * Created. * * 2001-January-27 Jason Rohrer * Switched to a ThreadSafePrinter in attempt to get it to work on Win32. * Changed print call to printf. * * 2002-November-14 Jason Rohrer * Added missing destructor. */ #include "minorGems/common.h" #ifndef TEST_THREAD_CLASS_INCLUDED #define TEST_THREAD_CLASS_INCLUDED #include "Thread.h" #include "ThreadSafePrinter.h" #include /** * Test subclass of Thread class. Useful for testing if platform-specific * thread implmentations are working. * * @author Jason Rohrer */ class TestThread : public Thread { public: /** * Constructs a test thread and tells it how high to count to. * * @param inID id number thread will print along with count. * @param inNumToCount thread will count from 0 to this number. */ TestThread( int inID, int inNumToCount ); ~TestThread(); // override the run method from PThread void run(); private: int mID; int mNumToCount; }; inline TestThread::TestThread( int inID, int inNumToCount ) : mID( inID ), mNumToCount( inNumToCount ) { } inline TestThread::~TestThread() { } inline void TestThread::run() { for( int i=0; i<=mNumToCount; i++ ) { ThreadSafePrinter::printf( "Thread %d counting %d.\n", mID, i ); } } #endif between-6+dfsg1.orig/minorGems/system/StopSignalThread.cpp0000640000175000017500000000231511435543337022455 0ustar pabspabs/* * Modification History * * 2002-April-4 Jason Rohrer * Created. * Changed to reflect the fact that the base class * destructor is called *after* the derived class destructor. * * 2002-August-5 Jason Rohrer * Fixed member initialization order to match declaration order. * * 2003-September-5 Jason Rohrer * Moved into minorGems. * * 2005-January-9 Jason Rohrer * Changed to sleep on a semaphore to make sleep interruptable by stop. */ #include "StopSignalThread.h" StopSignalThread::StopSignalThread() : mStopLock( new MutexLock() ), mStopped( false ), mSleepSemaphore( new BinarySemaphore() ) { } StopSignalThread::~StopSignalThread() { delete mStopLock; delete mSleepSemaphore; } void StopSignalThread::sleep( unsigned long inTimeInMilliseconds ) { mSleepSemaphore->wait( inTimeInMilliseconds ); } char StopSignalThread::isStopped() { mStopLock->lock(); char stoped = mStopped; mStopLock->unlock(); return stoped; } void StopSignalThread::stop() { mStopLock->lock(); mStopped = true; mStopLock->unlock(); // signal the semaphore to wake up the thread, if it is sleeping mSleepSemaphore->signal(); } between-6+dfsg1.orig/minorGems/system/linux/0000750000175000017500000000000011435543337017673 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/system/linux/ThreadLinux.cpp0000640000175000017500000001335411435543337022635 0ustar pabspabs/* * Modification History * * 2000-December-13 Jason Rohrer * Created. * * 2001-January-11 Jason Rohrer * Added missing sleep() implementation. * * 2002-March-27 Jason Rohrer * Added support for gprof-friendly thread wrappers. * Fixed a compile bug when gprof threads disabled. * * 2002-August-5 Jason Rohrer * Removed an unused variable. * * 2003-February-3 Jason Rohrer * Fixed sleep to be thread safe (signals were interrupting thread sleeps). * * 2004-March-31 Jason Rohrer * Added support for detatched mode. * * 2005-January-22 Jason Rohrer * Added a static sleep function. */ #include #include #include #include #include /** * Linux-specific implementation of the Thread class member functions. * * May also be compatible with other POSIX-like systems. * * To compile: * g++ -lpthread * If thread profiling is desired for gprof on linux, compile * with -DUSE_GPROF_THREADS (otherwise, only main thread is profiled). */ #ifdef USE_GPROF_THREADS // prototype int gprof_pthread_create( pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void * arg ); #endif // prototype /** * A wrapper for the run method, since pthreads won't take * a class's member function. Takes a pointer to the Thread to run, * cast as a void*; */ void *linuxThreadFunction( void * ); Thread::Thread() { // allocate a pthread structure on the heap mNativeObjectPointer = (void *)( new pthread_t[1] ); } Thread::~Thread() { // de-allocate the pthread structure from the heap pthread_t *threadPointer = (pthread_t *)mNativeObjectPointer; delete [] threadPointer; } void Thread::start( char inDetach ) { mIsDetached = inDetach; // get a pointer to the pthread pthread_t *threadPointer = (pthread_t *)mNativeObjectPointer; // create the pthread, which also sets it running #ifdef USE_GPROF_THREADS gprof_pthread_create( &( threadPointer[0] ), NULL, linuxThreadFunction, (void*)this ); #else pthread_create( &( threadPointer[0] ), NULL, linuxThreadFunction, (void*)this ); #endif if( mIsDetached ) { pthread_detach( threadPointer[0] ); } } void Thread::join() { void *joinStat; pthread_t *threadPointer = (pthread_t *)mNativeObjectPointer; pthread_join( threadPointer[0], &joinStat ); } void Thread::staticSleep( unsigned long inTimeInMilliseconds ) { unsigned long seconds = inTimeInMilliseconds / 1000; unsigned long milliseconds = inTimeInMilliseconds % 1000; struct timespec remainingSleepTimeStruct; remainingSleepTimeStruct.tv_sec = seconds; remainingSleepTimeStruct.tv_nsec = milliseconds * 1000000; struct timespec timeToSleepStruct; // sleep repeatedly, ignoring signals, untill we use up all of the time int sleepReturn = -1; while( sleepReturn == -1 ) { timeToSleepStruct.tv_sec = remainingSleepTimeStruct.tv_sec; timeToSleepStruct.tv_nsec = remainingSleepTimeStruct.tv_nsec; sleepReturn = nanosleep( &timeToSleepStruct, &remainingSleepTimeStruct ); } } // takes a pointer to a Thread object as the data value void *linuxThreadFunction( void *inPtrToThread ) { Thread *threadToRun = (Thread *)inPtrToThread; threadToRun->run(); if( threadToRun->isDetatched() ) { // thread detached, so we must destroy it delete threadToRun; } return inPtrToThread; } #ifdef USE_GPROF_THREADS // found at http://sam.zoy.org/doc/programming/gprof.html #include /* * pthread_create wrapper for gprof compatibility * * needed headers: * */ typedef struct wrapper_s { void * (*start_routine)(void *); void * arg; pthread_mutex_t lock; pthread_cond_t wait; struct itimerval itimer; } wrapper_t; static void * wrapper_routine(void *); /** * Same prototype as pthread_create; use some #define magic to * transparently replace it in other files */ int gprof_pthread_create( pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void * arg ) { wrapper_t wrapper_data; int i_return; /* Initialize the wrapper structure */ wrapper_data.start_routine = start_routine; wrapper_data.arg = arg; getitimer(ITIMER_PROF, &wrapper_data.itimer); pthread_cond_init(&wrapper_data.wait, NULL); pthread_mutex_init(&wrapper_data.lock, NULL); pthread_mutex_lock(&wrapper_data.lock); /* The real pthread_create call */ i_return = pthread_create(thread, attr, &wrapper_routine, &wrapper_data); /* If the thread was successfully spawned, wait for the data * to be released */ if( i_return == 0 ) { pthread_cond_wait(&wrapper_data.wait, &wrapper_data.lock); } pthread_mutex_unlock(&wrapper_data.lock); pthread_mutex_destroy(&wrapper_data.lock); pthread_cond_destroy(&wrapper_data.wait); return i_return; } /** * The wrapper function in charge for setting the itimer value */ static void * wrapper_routine( void * data ) { /* Put user data in thread-local variables */ void * (*start_routine)(void *) = ((wrapper_t*)data)->start_routine; void * arg = ((wrapper_t*)data)->arg; /* Set the profile timer value */ setitimer(ITIMER_PROF, &((wrapper_t*)data)->itimer, NULL); /* Tell the calling thread that we don't need its data anymore */ pthread_mutex_lock(&((wrapper_t*)data)->lock); pthread_cond_signal(&((wrapper_t*)data)->wait); pthread_mutex_unlock(&((wrapper_t*)data)->lock); /* Call the real function */ return start_routine(arg); } #endif between-6+dfsg1.orig/minorGems/system/linux/MutexLockLinux.cpp0000640000175000017500000000311311435543337023331 0ustar pabspabs/* * Modification History * * 2000-December-13 Jason Rohrer * Created. * * 2002-October-18 Jason Rohrer * Moved common include out of header and into platform-specific cpp files, * since MemoryTrack uses a mutex lock. * Changed to use malloc instead of new internally to work with debugMemory. * Made use of mNativeObjectPointer a bit cleaner. */ #include "minorGems/common.h" #include #include #include /** * Linux-specific implementation of the MutexLock class member functions. * * May also be compatible with other POSIX-like systems. * * To compile: * g++ -lpthread */ MutexLock::MutexLock() { // allocate a mutex structure on the heap mNativeObjectPointer = malloc( sizeof( pthread_mutex_t ) ); // get a pointer to the mutex pthread_mutex_t *mutexPointer = (pthread_mutex_t *)mNativeObjectPointer; // init the mutex pthread_mutex_init( mutexPointer, NULL ); } MutexLock::~MutexLock() { // get a pointer to the mutex pthread_mutex_t *mutexPointer = (pthread_mutex_t *)mNativeObjectPointer; // destroy the mutex pthread_mutex_destroy( mutexPointer ); // de-allocate the mutex structure from the heap free( mNativeObjectPointer ); } void MutexLock::lock() { // get a pointer to the mutex pthread_mutex_t *mutexPointer = (pthread_mutex_t *)mNativeObjectPointer; pthread_mutex_lock( mutexPointer ); } void MutexLock::unlock() { // get a pointer to the mutex pthread_mutex_t *mutexPointer = (pthread_mutex_t *)mNativeObjectPointer; pthread_mutex_unlock( mutexPointer ); } between-6+dfsg1.orig/minorGems/system/linux/BinarySemaphoreLinux.cpp0000640000175000017500000001103211435543337024505 0ustar pabspabs/* * Modification History * * 2001-January-11 Jason Rohrer * Created. * * 2003-August-26 Jason Rohrer * Added support for timeouts on wait. * * 2006-February-28 Jason Rohrer * Fixed bug in sub-second timeout computation. */ #include "minorGems/system/BinarySemaphore.h" #include "minorGems/system/Time.h" #include /** * Linux-specific implementation of the BinarySemaphore class member functions. * * May also be compatible with other POSIX-like systems. * * To compile: * g++ -lpthread */ /** * Native object pointer A is the condition variable. * Pointer B is the mutex that must go along with it. */ BinarySemaphore::BinarySemaphore() : mSemaphoreValue( 0 ) { // allocate a condition variable structure on the heap mNativeObjectPointerA = (void *)( new pthread_cond_t[1] ); // get a pointer to the cond pthread_cond_t *condPointer = (pthread_cond_t *)mNativeObjectPointerA; // init the cond pthread_cond_init( &( condPointer[0] ), NULL ); // allocate a mutex structure on the heap mNativeObjectPointerB = (void *)( new pthread_mutex_t[1] ); // get a pointer to the mutex pthread_mutex_t *mutexPointer = (pthread_mutex_t *)mNativeObjectPointerB; // init the mutex pthread_mutex_init( &( mutexPointer[0] ), NULL ); } BinarySemaphore::~BinarySemaphore() { // get a pointer to the cond pthread_cond_t *condPointer = (pthread_cond_t *)mNativeObjectPointerA; // destroy the cond pthread_cond_destroy( &( condPointer[0] ) ); // de-allocate the cond structure from the heap delete [] condPointer; // get a pointer to the mutex pthread_mutex_t *mutexPointer = (pthread_mutex_t *)mNativeObjectPointerB; // destroy the mutex pthread_mutex_destroy( &( mutexPointer[0] ) ); // de-allocate the mutex structure from the heap delete [] mutexPointer; } int BinarySemaphore::wait( int inTimeoutInMilliseconds ) { int returnValue = 1; // get a pointer to the cond pthread_cond_t *condPointer = (pthread_cond_t *)mNativeObjectPointerA; // get a pointer to the mutex pthread_mutex_t *mutexPointer = (pthread_mutex_t *)mNativeObjectPointerB; // lock the mutex pthread_mutex_lock( &( mutexPointer[0] ) ); if( mSemaphoreValue == 0 ) { // wait on condition variable, which automatically unlocks // the passed-in mutex if( inTimeoutInMilliseconds == -1 ) { // no timeout pthread_cond_wait( &( condPointer[0] ), &( mutexPointer[0] ) ); } else { // use timeout version unsigned long nsecPerSecond = 1000000000; unsigned long nsecPerMillisecond = 1000000; unsigned long currentSec; unsigned long currentMS; Time::getCurrentTime( ¤tSec, ¤tMS ); unsigned long currentNS = currentMS * nsecPerMillisecond; long timeoutSec = inTimeoutInMilliseconds / 1000; long extraMS = inTimeoutInMilliseconds % 1000; long extraNS = extraMS * nsecPerMillisecond; unsigned long absTimeoutSec = currentSec + timeoutSec; unsigned long absTimeoutNsec = currentNS + extraNS; // check for nsec overflow if( absTimeoutNsec > nsecPerSecond ) { absTimeoutSec += 1; absTimeoutNsec -= nsecPerSecond; } struct timespec abstime; abstime.tv_sec = absTimeoutSec; abstime.tv_nsec = absTimeoutNsec; int result = pthread_cond_timedwait( &( condPointer[0] ), &( mutexPointer[0] ), &abstime ); if( result != 0 ) { // timed out returnValue = 0; } } // mutex is apparently re-locked when we return from cond_wait } // decrement the semaphore value mSemaphoreValue = 0; // unlock the mutex again pthread_mutex_unlock( &( mutexPointer[0] ) ); return returnValue; } void BinarySemaphore::signal() { // get a pointer to the cond pthread_cond_t *condPointer = (pthread_cond_t *)mNativeObjectPointerA; // get a pointer to the mutex pthread_mutex_t *mutexPointer = (pthread_mutex_t *)mNativeObjectPointerB; // lock the mutex pthread_mutex_lock( &( mutexPointer[0] ) ); // increment the semaphore value mSemaphoreValue = 1; pthread_cond_signal( &( condPointer[0] ) ); // unlock the mutex pthread_mutex_unlock( &( mutexPointer[0] ) ); } between-6+dfsg1.orig/minorGems/system/FinishedSignalThread.h0000640000175000017500000000326511435543337022733 0ustar pabspabs/* * Modification History * * 2002-March-9 Jason Rohrer * Created. * * 2002-March-10 Jason Rohrer * Made destructor public. * * 2002-March-11 Jason Rohrer * Changed so that destructor joins thread. * * 2002-April-4 Jason Rohrer * Changed name of lock to avoid confusion with subclass-provided locks. * * 2004-April-1 Jason Rohrer * Moved from konspire2b into minorGems. * Changed so that destructor does not join the thread. * * 2004-November-19 Jason Rohrer * Changed to virtual inheritance from Thread class. */ #ifndef FINISHED_SIGNAL_THREAD_INCLUDED #define FINISHED_SIGNAL_THREAD_INCLUDED #include "minorGems/system/Thread.h" #include "minorGems/system/MutexLock.h" /** * Abstract subclass if thread that has a * synchronized finished signal. * * @author Jason Rohrer */ class FinishedSignalThread : public virtual Thread { public: /** * Only destroys this thread. * Does not join. */ virtual ~FinishedSignalThread(); /** * Gets whether this thread is finished and * ready to be destroyed. * * @return true iff this thread is finished. */ char isFinished(); protected: FinishedSignalThread(); /** * Sets that this thread is finished and * ready to be destroyed. * * For this class to work properly, the subclass * MUST call this function at the end of its run method. */ void setFinished(); private: MutexLock *mFinishedLock; char mFinished; }; #endif between-6+dfsg1.orig/minorGems/system/FinishedSignalThreadManager.h0000640000175000017500000000273611435543337024230 0ustar pabspabs/* * Modification History * * 2004-November-9 Jason Rohrer * Created. * Modified from MUTE's ChannelReceivingThreadManager. * * 2005-January-9 Jason Rohrer * Changed to sleep on a semaphore to allow sleep to be interrupted. */ #ifndef FINISHED_SIGNAL_THREAD_MANAGER_INCLUDED #define FINISHED_SIGNAL_THREAD_MANAGER_INCLUDED #include "minorGems/system/FinishedSignalThread.h" #include "minorGems/util/SimpleVector.h" #include "minorGems/system/Thread.h" #include "minorGems/system/MutexLock.h" #include "minorGems/system/BinarySemaphore.h" /** * A thread that manages the destruction of FinishedSignalThreads. * * @author Jason Rohrer. */ class FinishedSignalThreadManager : public Thread { public: /** * Constructs and starts this manager. */ FinishedSignalThreadManager(); /** * Stops and destroys this manager. */ ~FinishedSignalThreadManager(); /** * Adds a thread to this manager. * * @param inThread the thread to add. * Will be destroyed by this class. */ void addThread( FinishedSignalThread *inThread ); // implements the Thread interface void run(); protected: MutexLock *mLock; SimpleVector *mThreadVector; char mStopSignal; BinarySemaphore *mSleepSemaphore; }; #endif between-6+dfsg1.orig/minorGems/system/ThreadSafePrinter.h0000640000175000017500000000262711435543337022267 0ustar pabspabs/* * Modification History * * 2000-October-14 Jason Rohrer * Created. * * 2001-January-27 Jason Rohrer * Converted to use MutexLock and added to minorGems source tree. * Changed tprintf to be static (the mutexes don't work otherwise). * Now we're closing the argument list. * Fixed so that it works with any number of arguments. * Changed name of print function to printf. * * 2004-March-31 Jason Rohrer * Fixed static memory leak. */ #include "minorGems/common.h" #ifndef THREAD_SAFE_PRINTER_INCLUDED #define THREAD_SAFE_PRINTER_INCLUDED #include "MutexLock.h" #include // for variable argument lists #include /** * Thread safe printf function. Note that printf is actually thread safe * anyway, so this is just to demonstrate and test locks. It seems as * though printf _isn't_ thread safe on certain platforms, so this class * may be useful. * * @author Jason Rohrer */ class ThreadSafePrinter { public: static int printf( const char* inFormatString, ... ); private: static MutexLock sLock; }; // initialize static members MutexLock ThreadSafePrinter::sLock; inline int ThreadSafePrinter::printf( const char*inFormatString, ... ) { va_list argList; va_start( argList, inFormatString ); sLock.lock(); int returnVal = vprintf( inFormatString, argList ); fflush( stdout ); sLock.unlock(); va_end( argList ); return returnVal; } #endif between-6+dfsg1.orig/minorGems/system/Thread.h0000640000175000017500000000560711435543337020125 0ustar pabspabs/* * Modification History * * 2000-December-13 Jason Rohrer * Created. * * 2001-March-4 Jason Rohrer * Made sleep() static so it can be called by non-Thread classes. * * 2001-May-12 Jason Rohrer * Added comments about joining before destroying. * * 2002-March-29 Jason Rohrer * Added Fortify inclusion. * * 2002-August-5 Jason Rohrer * Made destructor virtual. * * 2004-March-31 Jason Rohrer * Added support for detatched mode. * * 2005-January-9 Jason Rohrer * Made sleep function virtual to allow overrides. * * 2005-January-22 Jason Rohrer * Added a static sleep function. */ #include "minorGems/common.h" #ifndef THREAD_CLASS_INCLUDED #define THREAD_CLASS_INCLUDED #ifdef FORTIFY #include "minorGems/util/development/fortify/fortify.h" #endif /** * Base class to be subclassed by all threads. * * Note: Implementation for the functions defined here is provided * separately for each platform (in the mac/ linux/ and win32/ * subdirectories). * * @author Jason Rohrer */ class Thread { public: Thread(); virtual ~Thread(); /** * Starts this Thread. * * Note that after starting a non-detached thread, it _must_ be * joined before being destroyed to avoid memory leaks. * * Threads running in detatched mode handle their own destruction * as they terminate and do not need to be joined at all. * * @param inDetach true if this thread should run in detatched mode, * or false to run in non-detached mode. Defaults to false. */ void start( char inDetach = false ); /** * To be overriden by subclasses. * This method will be run by the Thread after start() has been called. */ virtual void run() = 0; /** * Blocks until this thread finishes executing its run() method. * * Must be called before destroying this thread, if this thread * has been started. */ void join(); /** * Puts the current thread to sleep for a specified amount of time. * * Note that given a thread instance threadA, calling threadA.sleep() * will put the calling thread to sleep. * * @param inTimeInMilliseconds the number of milliseconds to sleep. */ virtual void sleep( unsigned long inTimeInMilliseconds ) { staticSleep( inTimeInMilliseconds ); } /** * Same as sleep, but can be called without constructing a thread. */ static void staticSleep( unsigned long inTimeInMilliseconds ); /** * Gets whether this thread is detached. * * @return true if this thread is detached. */ char isDetatched() { return mIsDetached; } private: /** * Used by platform-specific implementations. */ void *mNativeObjectPointer; char mIsDetached; }; #endif between-6+dfsg1.orig/minorGems/system/TestThread.cpp0000640000175000017500000000231711435543337021313 0ustar pabspabs/* * Modification History * * 2000-December-13 Jason Rohrer * Created. * * 2002-November-14 Jason Rohrer * Added more verbose printouts. * * 2004-March-31 Jason Rohrer * Added test of detached threads. */ #include "TestThread.h" int numToCount = 1000; /** * Main method that spawns two TestThreads. * * @author Jason Rohrer */ int main() { TestThread *thread1 = new TestThread( 1, numToCount ); TestThread *thread2 = new TestThread( 2, numToCount ); TestThread *thread3 = new TestThread( 3, numToCount ); ThreadSafePrinter::printf( "Starting thread 1\n" ); thread1->start(); ThreadSafePrinter::printf( "Starting thread 2\n" ); thread2->start(); ThreadSafePrinter::printf( "Starting thread 3 in detached mode\n" ); thread3->start( true ); Thread::sleep( 5000 ); ThreadSafePrinter::printf( "Joining thread 1\n" ); thread1->join(); ThreadSafePrinter::printf( "Joining thread 2\n" ); thread2->join(); ThreadSafePrinter::printf( "Destroying thread 1\n" ); delete thread1; ThreadSafePrinter::printf( "Destroying thread 2\n" ); delete thread2; ThreadSafePrinter::printf( "Thread 3 should handle its own destruction.\n" ); return 0; } between-6+dfsg1.orig/minorGems/system/StopSignalThread.h0000640000175000017500000000361611435543337022127 0ustar pabspabs/* * Modification History * * 2002-April-4 Jason Rohrer * Created. * Changed to reflect the fact that the base class * destructor is called *after* the derived class destructor. * * 2003-September-5 Jason Rohrer * Moved into minorGems. * * 2004-November-19 Jason Rohrer * Changed to virtual inheritance from Thread class. * * 2005-January-9 Jason Rohrer * Changed to sleep on a semaphore to make sleep interruptable by stop. */ #ifndef STOP_SIGNAL_THREAD_INCLUDED #define STOP_SIGNAL_THREAD_INCLUDED #include "minorGems/system/Thread.h" #include "minorGems/system/MutexLock.h" #include "minorGems/system/BinarySemaphore.h" /** * Abstract subclass of thread that has a stop signal. * * Note that subclasses MUST check the isStopped() function * periodically in their run() function for this class to work * properly. * * @author Jason Rohrer */ class StopSignalThread : public virtual Thread { public: /** * Only destroys this thread. * Does not stop or join. */ virtual ~StopSignalThread(); protected: StopSignalThread(); // overrides Thread::sleep to make it interruptable by our stop call virtual void sleep( unsigned long inTimeInMilliseconds ); /** * Signals this thread to stop, interrupting it if it is sleeping. * * Thread safe. * * Thread must be joined after this call returns. */ void stop(); /** * Gets whether this thread has been signaled to stop. * * Thread safe. * * @return true if this thread should stop. */ char isStopped(); private: MutexLock *mStopLock; char mStopped; BinarySemaphore *mSleepSemaphore; }; #endif between-6+dfsg1.orig/minorGems/system/win32/0000750000175000017500000000000011435543337017476 5ustar pabspabsbetween-6+dfsg1.orig/minorGems/system/win32/ThreadWin32.cpp0000640000175000017500000000456011435543337022242 0ustar pabspabs/* * Modification History * * 2001-January-27 Jason Rohrer * Created. * * 2001-March-4 Jason Rohrer * Replaced include of and with * to fix compile bugs encountered with newer windows compilers. * * 2004-March-31 Jason Rohrer * Added missing call to CloseHandle in destructor. * Added support for detatched mode. * * 2004-April-1 Jason Rohrer * Fixed a bug in CloseHandle call pointed out by Mycroftxxx. * * 2005-January-22 Jason Rohrer * Added a static sleep function. */ #include "minorGems/system/Thread.h" #include /** * Win32-specific implementation of the Thread class member functions. * */ // prototype /** * A wrapper for the run method, since windows thread (perhaps) won't take * a class's member function. Takes a pointer to the Thread to run, * cast as a void*; */ DWORD WINAPI win32ThreadFunction( void * ); Thread::Thread() { // allocate a handle on the heap mNativeObjectPointer = (void *)( new HANDLE[1] ); } Thread::~Thread() { // get a pointer to the allocated handle HANDLE *threadPointer = (HANDLE *)mNativeObjectPointer; // close the handle to ensure that the thread resources are freed CloseHandle( threadPointer[0] ); // de-allocate the thread handle from the heap delete [] threadPointer; } void Thread::start( char inDetach ) { mIsDetached = inDetach; // get a pointer to the allocated handle HANDLE *threadPointer = (HANDLE *)mNativeObjectPointer; DWORD threadID; threadPointer[0] = CreateThread( (LPSECURITY_ATTRIBUTES)NULL, // no attributes (DWORD)0, // default stack size win32ThreadFunction, // function (LPVOID)this, // function arg (DWORD)0, // no creation flags (start thread immediately) &threadID ); } void Thread::join() { HANDLE *threadPointer = (HANDLE *)mNativeObjectPointer; WaitForSingleObject( threadPointer[0], INFINITE ); } void Thread::staticSleep( unsigned long inTimeInMilliseconds ) { Sleep( inTimeInMilliseconds ); } // takes a pointer to a Thread object as the data value DWORD WINAPI win32ThreadFunction( void *inPtrToThread ) { Thread *threadToRun = (Thread *)inPtrToThread; threadToRun->run(); if( threadToRun->isDetatched() ) { // thread detached, so we must destroy it delete threadToRun; } return 0; } between-6+dfsg1.orig/minorGems/system/win32/BinarySemaphoreWin32.cpp0000640000175000017500000000401711435543337024120 0ustar pabspabs/* * Modification History * * 2001-January-27 Jason Rohrer * Created. * * 2001-March-4 Jason Rohrer * Replaced include of and with * to fix compile bugs encountered with newer windows compilers. * * 2003-August-26 Jason Rohrer * Added support for timeouts on wait. */ #include "minorGems/system/BinarySemaphore.h" #include /** * Win32-specific implementation of the BinarySemaphore class member functions. */ /** * Native object pointer A is the semaphore handle. * Pointer B is not used. */ BinarySemaphore::BinarySemaphore() : mSemaphoreValue( 0 ) { // allocate a handle on the heap mNativeObjectPointerA = (void *)( new HANDLE[1] ); // retrieve handle from the heap HANDLE *semaphorePointer = (HANDLE *)mNativeObjectPointerA; semaphorePointer[0] = CreateSemaphore( (LPSECURITY_ATTRIBUTES) NULL, // no attributes 0, // initial count 1, // maximum count (LPCTSTR) NULL ); // no name } BinarySemaphore::~BinarySemaphore() { // retrieve handle from the heap HANDLE *semaphorePointer = (HANDLE *)mNativeObjectPointerA; // destroy the semaphore CloseHandle( semaphorePointer[0] ); // de-allocate the handle from the heap delete [] semaphorePointer; } int BinarySemaphore::wait( int inTimeoutInMilliseconds ) { // retrieve handle from the heap HANDLE *semaphorePointer = (HANDLE *)mNativeObjectPointerA; if( inTimeoutInMilliseconds == -1 ) { WaitForSingleObject( semaphorePointer[0], INFINITE ); return 1; } else { // timeout int result = WaitForSingleObject( semaphorePointer[0], inTimeoutInMilliseconds ); if( result == WAIT_TIMEOUT ) { return 0; } else { return 1; } } } void BinarySemaphore::signal() { // retrieve handle from the heap HANDLE *semaphorePointer = (HANDLE *)mNativeObjectPointerA; ReleaseSemaphore( semaphorePointer[0], 1, (LPLONG) NULL ); } between-6+dfsg1.orig/minorGems/system/win32/LauncherWin32.cpp0000640000175000017500000000065011435543337022570 0ustar pabspabs/* * Modification History * * 2003-January-10 Jason Rohrer * Created. * * 2003-March-24 Jason Rohrer * Fixed a syntax typo. */ #include "minorGems/system/Launcher.h" #include #include void Launcher::launchCommand( char *inCommandName, char **inArguments ) { _spawnvp( _P_NOWAIT, inCommandName, inArguments ); } between-6+dfsg1.orig/minorGems/system/win32/MutexLockWin32.cpp0000640000175000017500000000341111435543337022740 0ustar pabspabs/* * Modification History * * 2001-January-27 Jason Rohrer * Created. * * 2001-March-4 Jason Rohrer * Replaced include of and with * to fix compile bugs encountered with newer windows compilers. * * 2002-October-18 Jason Rohrer * Moved common include out of header and into platform-specific cpp files, * since MemoryTrack uses a mutex lock. * * 2002-October-19 Jason Rohrer * Changed to use malloc instead of new internally to work with debugMemory. * Made use of mNativeObjectPointer a bit cleaner. * Fixed a few bugs with new use of mNativeObjectPointer. */ #include "minorGems/common.h" #include "minorGems/system/MutexLock.h" #include #include /** * Win32-specific implementation of the MutexLock class member functions. */ MutexLock::MutexLock() { // allocate a handle on the heap mNativeObjectPointer = malloc( sizeof( HANDLE ) ); // retrieve handle from the heap HANDLE *mutexPointer = (HANDLE *)mNativeObjectPointer; // create the mutex *mutexPointer = CreateMutex( (LPSECURITY_ATTRIBUTES) NULL, // no attributes (BOOL) false, // not initially locked (LPCTSTR) NULL ); // no name } MutexLock::~MutexLock() { // retrieve handle from the heap HANDLE *mutexPointer = (HANDLE *)mNativeObjectPointer; // destroy the mutex CloseHandle( *mutexPointer ); // de-allocate the mutex structure from the heap free( mutexPointer ); } void MutexLock::lock() { // retrieve handle from the heap HANDLE *mutexPointer = (HANDLE *)mNativeObjectPointer; WaitForSingleObject( *mutexPointer, INFINITE ); } void MutexLock::unlock() { // retrieve handle from the heap HANDLE *mutexPointer = (HANDLE *)mNativeObjectPointer; ReleaseMutex( *mutexPointer ); } between-6+dfsg1.orig/minorGems/system/win32/TimeWin32.cpp0000640000175000017500000000447011435543337021731 0ustar pabspabs/* * Modification History * * 2001-November-7 Jason Rohrer * Created. * * 2002-April-11 Jason Rohrer * Added missing include, and fixed a bug. * * 2004-January-29 Jason Rohrer * Fixed so that 0-point of time is the same as on other platforms. * * 2004-October-14 Jason Rohrer * Fixed bug in second/millisecond callibration. * Fixed bug in win32 time to ANSI time translation. * Fixed daylight savings time bug. */ #include "minorGems/system/Time.h" #include #include #include #include /** * Windows implementation of Time.h. * * The 0-point should match the ANSI standard. */ void Time::getCurrentTime( unsigned long *outSeconds, unsigned long *outMilliseconds ) { // convert from win32 broken-down time (which has msec resolution) // to an ANSI time struct and then convert to an absolute time in // seconds // This procedure ensures that the 0-point matches the ANSI standard. // note: // we cannot simply call ANSI time() to get the seconds and then rely // on GetLocalTime to get the milliseconds, since the seconds value // used by GetLocalTime is (strangely enough) not calibrated to the seconds // value of time(). // In other words, it is possible for the time() seconds to advance // at a different clock cycle than the GetLocalTime seconds. // get time using a win32 call SYSTEMTIME win32TimeStruct; GetLocalTime( &win32TimeStruct ); // convert this win32 structure to the ANSI standard structure struct tm ansiTimeStruct; ansiTimeStruct.tm_sec = win32TimeStruct.wSecond; ansiTimeStruct.tm_min = win32TimeStruct.wMinute; ansiTimeStruct.tm_hour = win32TimeStruct.wHour; ansiTimeStruct.tm_mday = win32TimeStruct.wDay; // ANSI time struct has month in range [0..11] ansiTimeStruct.tm_mon = win32TimeStruct.wMonth - 1; // ANSI time struct has year that is an offset from 1900 ansiTimeStruct.tm_year = win32TimeStruct.wYear - 1900; // unknown daylight savings time (dst) status // if we fail to init this value, we can get inconsistent results ansiTimeStruct.tm_isdst = -1; unsigned long secondsSinceEpoch = mktime( &ansiTimeStruct ); *outSeconds = secondsSinceEpoch; *outMilliseconds = (unsigned long)( win32TimeStruct.wMilliseconds ); } between-6+dfsg1.orig/runToBuild0000750000175000017500000000110211435543355015257 0ustar pabspabs#!/bin/bash # # Modification History # # 2007-November-12 Jason Rohrer # Copied from Cultivation. # cd game7 chmod u+x ./configure ./configure cd gameSource echo "Building Between..." make cd ../.. mkdir graphics mkdir music mkdir settings mkdir languages cp game7/gameSource/Between ./Between cp game7/documentation/Readme.txt . cp game7/gameSource/graphics/* ./graphics cp game7/gameSource/music/* ./music cp game7/gameSource/settings/* ./settings cp game7/gameSource/languages/* ./languages cp game7/gameSource/language.txt ./ echo "Run Between to play."