passage-4+dfsg1.orig/0000750000175000017500000000000011376537560013245 5ustar pabspabspassage-4+dfsg1.orig/gamma256/0000750000175000017500000000000011376537567014573 5ustar pabspabspassage-4+dfsg1.orig/gamma256/gameSource/0000750000175000017500000000000011376537567016665 5ustar pabspabspassage-4+dfsg1.orig/gamma256/gameSource/game.cpp0000640000175000017500000010457111375555301020274 0ustar pabspabs/* * Modification History * * 2007-September-25 Jason Rohrer * Created. */ #include #include #include #include #include // for memcpy #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 "blowUp.h" #include "World.h" #include "map.h" #include "score.h" #include "common.h" #include "musicPlayer.h" #include "minorGems/system/Time.h" #include "minorGems/system/Thread.h" #include "minorGems/util/stringUtils.h" #include "minorGems/util/SettingsManager.h" // size of game image int width = 100; int height = 12; // area above game image for score int scoreHeight = getScoreHeight(); // size of game image plus scoreboard int totalImageHeight = height + scoreHeight; char paused = false; char canPause = false; // size of screen for fullscreen mode int screenWidth = 640; int screenHeight = 480; //int screenWidth = 100; //int screenHeight = 16; // blow-up factor when projecting game onto screen // Max defined by image size vs screen size. // This is the cap for in-game user-directed blowup adjustment. int maxBlowUpFactor; // current blow-up setting int blowUpFactor; // step to take when user hits blowUp key int blowUpStep = -1; // flag to force update of entire screen int blowUpChanged = true; char fullScreen = true; // lock down to 15 fps int lockedFrameRate = 15; // target length of game int gameTime = 5 * 60; //int gameTime = 30; // life time that passes per frame double timeDelta = - ( (double)width / ( gameTime * lockedFrameRate ) ); //double timeDelta = -0.0; // the joystick to read from, or NULL if there's no available joystick SDL_Joystick *joystick; // catch an interrupt signal void catch_int(int sig_num) { printf( "Quiting...\n" ); SDL_Quit(); exit( 0 ); signal( SIGINT, catch_int ); } char getKeyDown( int inKeyCode ) { SDL_PumpEvents(); Uint8 *keys = SDL_GetKeyState( NULL ); return keys[ inKeyCode ] == SDL_PRESSED; } char getHatDown( Uint8 inHatPosition ) { if( joystick == NULL ) { return false; } SDL_JoystickUpdate(); Uint8 hatPosition = SDL_JoystickGetHat( joystick, 0 ); if( hatPosition & inHatPosition ) { return true; } else { return false; } } int joyThreshold = 25000; char getJoyPushed( Uint8 inHatPosition ) { Sint16 x = SDL_JoystickGetAxis(joystick, 0); Sint16 y = SDL_JoystickGetAxis(joystick, 1); switch( inHatPosition ) { case SDL_HAT_DOWN: return y > joyThreshold; break; case SDL_HAT_UP: return y < -joyThreshold; break; case SDL_HAT_LEFT: return x < - joyThreshold; break; case SDL_HAT_RIGHT: return x > joyThreshold; break; default: return false; } } // returns true if hit, returns false if user quits before hitting char waitForKeyOrButton() { SDL_Event event; while( true ) { while( SDL_WaitEvent( &event ) ) { switch( event.type ) { case SDL_JOYHATMOTION: case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: case SDL_KEYDOWN: case SDL_KEYUP: return true; break; // watch for quit event case SDL_QUIT: return false; break; default: break; } } } return false; } Uint32 *gameImage; // flips back buffer onto screen (or updates rect) void flipScreen( SDL_Surface *inScreen ) { // unlock the screen if necessary if( SDL_MUSTLOCK( inScreen ) ) { SDL_UnlockSurface( inScreen ); } if( ( inScreen->flags & SDL_DOUBLEBUF ) == SDL_DOUBLEBUF ) { // need to flip buffer SDL_Flip( inScreen ); } else if( !blowUpChanged ) { // just update center // small area in center that we actually draw in, black around it int yOffset = ( inScreen->h - totalImageHeight * blowUpFactor ) / 2; int xOffset = ( inScreen->w - width * blowUpFactor ) / 2; SDL_UpdateRect( inScreen, xOffset, yOffset, width * blowUpFactor, totalImageHeight * blowUpFactor ); } else { // update the whole thing SDL_UpdateRect( inScreen, 0, 0, inScreen->w, inScreen->h ); // reset flag blowUpChanged = false; } } void lockScreen( SDL_Surface * inScreen ) { // check if we need to lock the screen if( SDL_MUSTLOCK( inScreen ) ) { if( SDL_LockSurface( inScreen ) < 0 ) { printf( "Couldn't lock screen: %s\n", SDL_GetError() ); } } } void flipGameImageOntoScreen( SDL_Surface *inScreen ) { if( blowUpChanged && ( inScreen->flags & SDL_DOUBLEBUF ) == SDL_DOUBLEBUF ) { // blow up size has changed, and we are double-buffered // flip onto screen an additional time. // This will cause us to black-out the background in both buffers. lockScreen( inScreen ); // when blow-up factor changes: // clear screen to prepare for next draw, // which will be bigger or smaller SDL_FillRect( inScreen, NULL, 0x00000000 ); blowupOntoScreen( gameImage, width, totalImageHeight, blowUpFactor, inScreen ); flipScreen( inScreen ); } lockScreen( inScreen ); if( blowUpChanged ) { SDL_FillRect( inScreen, NULL, 0x00000000 ); } blowupOntoScreen( gameImage, width, totalImageHeight, blowUpFactor, inScreen ); flipScreen( inScreen ); // we've handled any blow up change blowUpChanged = false; } SDL_Surface *screen = NULL; // play a complete game, from title screen to end, on screen // returns false if player quits char playGame(); void createScreen() { if( screen != NULL ) { // destroy old one first SDL_FreeSurface( screen ); } int displayW = width * blowUpFactor; int displayH = totalImageHeight * blowUpFactor; Uint32 flags = SDL_HWSURFACE | SDL_DOUBLEBUF; if( fullScreen ) { flags = flags | SDL_FULLSCREEN; // use letterbox mode in full screen displayW = screenWidth; displayH = screenHeight; } screen = SDL_SetVideoMode( displayW, displayH, 32, flags ); if ( screen == NULL ) { printf( "Couldn't set %dx%dx32 video mode: %s\n", displayW, displayH, SDL_GetError() ); } } int mainFunction( int inArgCount, char **inArgs ) { // let catch_int handle interrupt (^c) signal( SIGINT, catch_int ); Uint32 initFlags = SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE; #ifdef __mac__ // SDL_Init is dreadfully slow if we try to init JOYSTICK on MacOSX // not sure why---maybe it's searching all devices or something like // that. // Couldn't find anything online about this. initFlags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE; #endif if( SDL_Init( initFlags ) < 0 ) { printf( "Couldn't initialize SDL: %s\n", SDL_GetError() ); return -1; } SDL_ShowCursor( SDL_DISABLE ); // 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; } printf( "Screen dimensions for fullscreen mode: %dx%d\n", screenWidth, screenHeight ); // set here, since screenWidth may have changed from default maxBlowUpFactor = screenWidth / width; // default to max blowUpFactor = maxBlowUpFactor; char fullscreenFound = false; int readFullscreen = SettingsManager::getIntSetting( "fullscreen", &fullscreenFound ); if( fullscreenFound ) { fullScreen = readFullscreen; } printf( "Starting game in " ); if( fullScreen ) { printf( "fullscreen" ); } else { printf( "windowed" ); } printf( " mode.\n" ); createScreen(); // try to open joystick int numJoysticks = SDL_NumJoysticks(); printf( "Found %d joysticks\n", numJoysticks ); if( numJoysticks > 0 ) { // open first one by default joystick = SDL_JoystickOpen( 0 ); if( joystick == NULL ) { printf( "Couldn't open joystick 0: %s\n", SDL_GetError() ); } int numHats = SDL_JoystickNumHats( joystick ); if( numHats <= 0 ) { printf( "No d-pad found on joystick\n" ); SDL_JoystickClose( joystick ); joystick = NULL; } } else { joystick = NULL; } #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 ] ); printf( "Mac: app path %s\n", appDirectoryPath ); char *appNamePointer = strstr( appDirectoryPath, "Passage.app" ); if( appNamePointer != NULL ) { // terminate full app path to get parent directory appNamePointer[0] = '\0'; printf( "Mac: changing working dir to %s\n", appDirectoryPath ); chdir( appDirectoryPath ); } delete [] appDirectoryPath; #endif // load graphics only once loadWorldGraphics(); setMusicLoudness( 0 ); startMusic( "music.tga" ); // keep playing until player quits while( playGame() ) { } stopMusic(); destroyWorldGraphics(); if( joystick != NULL ) { SDL_JoystickClose( joystick ); } SDL_Quit(); return 0; } /* // TEMP #include "minorGems/graphics/converters/TGAImageConverter.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/FileInputStream.h" // END TEMP */ char playGame() { int currentSpriteIndex = 2; double playerX, playerY; double maxPlayerX = 0; int score = 0; // the gem that marks chests containing points int specialGem = time( NULL ) % 4; int exploreScore = 0; int exploreSubPoints = 0; // make sure explore score never goes down int maxExploreScore = 0; int chestScore = 0; // track whether we ever met the spouse // separate from World's haveMetSpouse() char knowSpouse = false; initWorld(); initScore(); // room at top for score int totalGameImagePixels = width * totalImageHeight; gameImage = new Uint32[ totalGameImagePixels ]; int i; // fill with black for( i=0; igetWidth() * titleImage->getHeight(); double *titleRed = titleImage->getChannel( 0 ); double *titleGreen = titleImage->getChannel( 1 ); double *titleBlue = titleImage->getChannel( 2 ); Uint32 *titlePixels = new Uint32[ numTitlePixels ]; for( int i=0; i> 16) & 0xFF ) / 255.0; muralG[ index ] = ( (sample >> 8) & 0xFF ) / 255.0; muralB[ index ] = ( sample & 0xFF ) / 255.0; } } } File tgaFile( NULL, "mural.tga" ); FileOutputStream tgaStream( &tgaFile ); TGAImageConverter converter; converter.formatImage( &mural, &tgaStream ); // END TEMP */ while( !done ) { if( getKeyDown( SDLK_s ) ) { stepDX = false; } else { stepDX = true; } // trick: // dX advances linearly, which results in smooth motion // instead of single-pixel tick-tick-tick // However, this results in smudgy sampling of sprites, which // makes them hard to see // If we map our sloping dX, which looks like this: / // to a constant between integers with a steep slope up to the next // integer, like this: _/ // Then we get to look at unsmudged sprites between steps, but // still see a smoothed-out tick double drawDX = floor( dX ); double floorWidth = 0.5; if( dX - drawDX > floorWidth ) { // slope double slopeValue = ( dX - drawDX - floorWidth ) / ( 1 - floorWidth ); // us trig function to avoid jagged transition from floor to // slope to next floor drawDX += -0.5 * cos( slopeValue * M_PI ) + 0.5; } if( !stepDX ) { // disable smoothed stepping drawDX = dX; } for( int y=0; y maxDistance ) { cappedDistanceFromPlayer = maxDistance; } if( cappedDistanceFromPlayer < -maxDistance ) { cappedDistanceFromPlayer = -maxDistance; } // the world position we will sample from double worldX = x; // zone around player where no x compression happens int noCompressZone = 10; if( trueDistanceFromPlayer > noCompressZone ) { worldX = x + //(width/8) * // use true distance as a factor so that compression // continues at constant rate after we pass capped // distance // otherwise, compression stops after capped distance // Still... constant rate looks weird, so avoid // it by not letting it pass capped distance trueDistanceFromPlayer / 2 * ( pow( tan( ( ( cappedDistanceFromPlayer - noCompressZone ) / (double)( width - noCompressZone ) ) * M_PI / 2 ), 2) ); /* trueDistanceFromPlayer / 2 * ( tan( ( cappedDistanceFromPlayer / (double)( width - 0.5 ) ) * M_PI / 2 ) ); */ // simpler formula // actually, this does not approach 0 as // cappedDistanceFromPlayer approaches 0, so use tan // instead // ( trueDistanceFromPlayer / 2 ) * 100 // / pow( ( width - cappedDistanceFromPlayer ), 1.6 ); } else if( trueDistanceFromPlayer < - noCompressZone ) { worldX = x + //(width/8) * trueDistanceFromPlayer / 2 * ( pow( tan( ( ( - cappedDistanceFromPlayer - noCompressZone ) / (double)( width - noCompressZone ) ) * M_PI / 2 ), 2) ); /* trueDistanceFromPlayer / 2 * ( tan( ( - cappedDistanceFromPlayer / (double)( width - 0.5 ) ) * M_PI / 2 ) ); */ //( trueDistanceFromPlayer / 2 ) * 50 /// ( width + cappedDistanceFromPlayer ); } else { // inside no-compresison zone worldX = x; } //int worldX = x; worldX += drawDX; if( worldX > maxWorldX ) { maxWorldX = worldX; } if( worldX < minWorldX ) { minWorldX = worldX; } int worldY = (int)floor( y + dY ); // linear interpolation of two samples for worldX int intWorldX = (int)floor( worldX ); double bWeight = worldX - intWorldX; double aWeight = 1 - bWeight; Uint32 sampleA = sampleFromWorld( intWorldX, worldY, aWeight ); Uint32 sampleB = sampleFromWorld( intWorldX + 1, worldY, bWeight ); Uint32 combined = sampleB + sampleA; gameImage[ ( y + scoreHeight ) * width + x ] = combined; } } drawScore( gameImage, width, height, score ); if( isPlayerDead() ) { // fade to title screen double titleWeight = titleFadeFrame / (double)( numTitleFadeFrames - 1 ); double gameWeight = 1 - titleWeight; // wipe from left to right during fade int wipePosition = (int)( titleWeight * width ); // fade out music while we do it setMusicLoudness( 1.0 - titleWeight ); for( i=0; i> 16 & 0xFF; unsigned char gameGreen = gamePixel >> 8 & 0xFF; unsigned char gameBlue = gamePixel & 0xFF; Uint32 titlePixel = titlePixels[i]; unsigned char titleRed = titlePixel >> 16 & 0xFF; unsigned char titleGreen = titlePixel >> 8 & 0xFF; unsigned char titleBlue = titlePixel & 0xFF; unsigned char red = (unsigned char)( gameWeight * gameRed + titleWeight * titleRed ); unsigned char green = (unsigned char)( gameWeight * gameGreen + titleWeight * titleGreen ); unsigned char blue = (unsigned char)( gameWeight * gameBlue + titleWeight * titleBlue ); int x = i % width; if( x <= wipePosition ) { gameImage[i] = red << 16 | green << 8 | blue; } } if( !paused ) { titleFadeFrame ++; } if( titleFadeFrame == numTitleFadeFrames ) { done = true; } } flipGameImageOntoScreen( screen ); // done with frame double newTimestamp = Time::getCurrentTime(); double frameTime = newTimestamp - lastFrameTimeStamp; double extraTime = 1.0 / lockedFrameRate - frameTime; if( extraTime > 0 ) { Thread::staticSleep( (int)( extraTime * 1000 ) ); } // start timing next frame lastFrameTimeStamp = Time::getCurrentTime(); int spouseX, spouseY; getSpousePosition( &spouseX, &spouseY ); int moveDelta = 1; if( isPlayerDead() ) { // stop moving moveDelta = 0; } if( knowSpouse && isSpouseDead() ) { // player moves slower // toggle motion on this frame movingThisFrame = ( frameCount % 2 == 0 ); } if( getKeyDown( SDLK_p ) && canPause ) { paused = true; } if( getKeyDown( SDLK_o ) ) { paused = false; } if( paused && getKeyDown( SDLK_i ) ) { stepAnimations(); } if( getKeyDown( SDLK_b ) ) { // adjust blowup factor blowUpFactor += blowUpStep; if( blowUpFactor > maxBlowUpFactor ) { blowUpStep *= -1; blowUpFactor = maxBlowUpFactor - 1; } if( blowUpFactor < 1 ) { blowUpStep *= -1; blowUpFactor = 2; } if( fullScreen ) { // force redraw of whole screen blowUpChanged = true; } else { // create a new screen using the new size createScreen(); } } if( getKeyDown( SDLK_f ) ) { // toggle fullscreen mode fullScreen = ! fullScreen; // create a new screen surface (and destroy old one) createScreen(); } if( getKeyDown( SDLK_LEFT ) || getJoyPushed( SDL_HAT_LEFT ) ) { char notBlocked = !isBlocked( (int)( playerX - moveDelta ), (int)playerY ); // spouse and character move, and are blocked, together if( haveMetSpouse() && isBlocked( spouseX - moveDelta, spouseY ) ) { notBlocked = false; } if( movingThisFrame && notBlocked ) { playerX -= moveDelta; if( playerX < 0 ) { // undo playerX += moveDelta; } else { // update screen position dX -= moveDelta; // pick sprite frame based on position in world if( ( (int)playerX / 2 ) % 2 == 0 ) { currentSpriteIndex = 6; } else { currentSpriteIndex = 7; } } } } else if( getKeyDown( SDLK_RIGHT ) || getJoyPushed( SDL_HAT_RIGHT )) { char notBlocked = !isBlocked( (int)( playerX + moveDelta ), (int)playerY ); // spouse and character move, and are blocked, together if( haveMetSpouse() && isBlocked( spouseX + moveDelta, spouseY ) ) { notBlocked = false; } if( movingThisFrame && notBlocked ) { dX += moveDelta; playerX += moveDelta; // pick sprite frame based on position in world if( ( (int)playerX / 2 ) % 2 == 0 ) { currentSpriteIndex = 3; } else { currentSpriteIndex = 2; } } } else if( getKeyDown( SDLK_UP ) || getJoyPushed( SDL_HAT_UP ) ) { char notBlocked = !isBlocked( (int)playerX, (int)( playerY - moveDelta ) ); // spouse and character move, and are blocked, together if( haveMetSpouse() && isBlocked( spouseX, spouseY - moveDelta ) ) { notBlocked = false; } if( movingThisFrame && notBlocked ) { playerY -= moveDelta; if( playerY < 0 ) { // undo playerY += moveDelta; } else { // update screen position dY -= moveDelta; // pick sprite frame based on position in world if( ( (int)playerY / 2 ) % 2 == 0 ) { currentSpriteIndex = 0; } else { currentSpriteIndex = 1; } } } } else if( getKeyDown( SDLK_DOWN ) || getJoyPushed( SDL_HAT_DOWN )) { char notBlocked = !isBlocked( (int)playerX, (int)( playerY + moveDelta ) ); // spouse and character move, and are blocked, together if( haveMetSpouse() && isBlocked( spouseX, spouseY + moveDelta ) ) { notBlocked = false; } if( movingThisFrame && notBlocked ) { dY += moveDelta; playerY += moveDelta; // pick sprite frame based on position in world if( ( (int)playerY / 2 ) % 2 == 0 ) { currentSpriteIndex = 5; } else { currentSpriteIndex = 4; } } } setPlayerPosition( (int)playerX, (int)playerY ); setPlayerSpriteFrame( currentSpriteIndex ); // may change after we set player position getSpousePosition( &spouseX, &spouseY ); // check for events to quit SDL_Event event; while( SDL_PollEvent(&event) ) { switch( event.type ) { case SDL_KEYDOWN: switch( event.key.keysym.sym ) { case SDLK_q: case SDLK_ESCAPE: done = true; quit = true; break; default: break; } break; case SDL_QUIT: done = true; quit = true; break; default: break; } } //t +=0.25; frameCount ++; // other animations run independent of whether player is moving if( !paused && frameCount % 6 == 0 ) { stepAnimations(); } if( ! isPlayerDead() && ! paused ) { // player position on screen inches forward dX += timeDelta; } double age = ( playerX - dX ) / width; setCharacterAges( age ); if( age >= 0.85 ) { dieSpouse(); } if( age >= 0.95 ) { diePlayer(); } if( isChest( (int)playerX, (int)playerY ) == CHEST_CLOSED ) { openChest( (int)playerX, (int)playerY ); int chestX, chestY; getChestCenter( (int)playerX, (int)playerY, &chestX, &chestY ); if( getChestCode( (int)playerX, (int)playerY ) & 0x01 << specialGem ) { // reward player chestScore += 100; startPrizeAnimation( chestX, chestY ); } else { startDustAnimation( chestX, chestY ); } } int distanceFromSpouse = (int) sqrt( pow( spouseX - playerX, 2 ) + pow( spouseY - playerY, 2 ) ); if( ! haveMetSpouse() && ! isSpouseDead() && distanceFromSpouse < 10 ) { meetSpouse(); knowSpouse = true; startHeartAnimation( (int)( ( spouseX - playerX ) / 2 + playerX ), (int)( ( spouseY - playerY ) / 2 + playerY ) - 2 ); } // stop after player has gone off right end of screen if( playerX - dX > width ) { dX = playerX - width; } int exploreDelta = 0; if( playerX > maxPlayerX ) { exploreDelta = (int)( playerX - maxPlayerX ); maxPlayerX = playerX; } int spouseExploreFactor = 2; if( haveMetSpouse() ) { // exploring worth more exploreDelta *= spouseExploreFactor; } exploreSubPoints += exploreDelta; exploreScore = (int)( exploreSubPoints / 10 ); if( haveMetSpouse() ) { // show explore score contribution in jumps exploreScore = ( exploreScore / spouseExploreFactor ) * spouseExploreFactor; // note: // this can cause our score to go down (to the previous // jump) as we transition from not having a spouse to // having one. // we fix this below with maxExploreScore } if( exploreScore < maxExploreScore ) { // don't let it go down from max exploreScore = maxExploreScore; } score = chestScore + exploreScore; if( exploreScore > maxExploreScore ) { maxExploreScore = exploreScore; } } unsigned long netTime = time( NULL ) - startTime; double frameRate = frameCount / (double)netTime; printf( "Max world x = %f\n", maxWorldX ); printf( "Min world x = %f\n", minWorldX ); printf( "Frame rate = %f fps (%d frames)\n", frameRate, frameCount ); printf( "Game time = %d:%d\n", (int)netTime / 60, (int)netTime % 60 ); fflush( stdout ); delete titleImage; delete [] gameImage; delete [] titlePixels; destroyWorld(); destroyScore(); if( quit ) { return false; } else { return true; } } passage-4+dfsg1.orig/gamma256/gameSource/characterSprite.png0000640000175000017500000000217710710626104022477 0ustar pabspabsPNG  IHDR#P [aFIDATh홿k#9ߘI \uа.OČH:osa!W;i%E8e@pc07.\\![8gU-|{ΊBQpmu7|oƒ`+Un+KK?WYg+2qes!_K(E`𽩔X, !"}fWQ[ʹJj&lMzJo~λV؆+)tjZXyJRM_`fzUB 8;"t$JZ 4a`f=eeYBJ$D8KIXr:i2rK |Թ#(K+|ܚ73E%N!%YxCrd<4[jЛ.opޘ\o['r%Pr~mfy*5OPvejTR@.O%;sNҊ4f*&S[E;9Bby|zEMd /Kc%j/w" cZkcL 7?ޚ֔͏!G㝝ѫW۱[ւK)~^_E\4vLl'ny+27a7p&p0qz'U}Nn`}K~ZYVnoh @3TV2.+a}f r)r[H2Ν[kњ GB0Rh1N6zIKr.4-;n7`:ӳ/ךra*@r˧G/c?&=:MEO֔RƘټu~9J?\8#RC9ndhpIENDB`passage-4+dfsg1.orig/gamma256/gameSource/blowUp.cpp0000640000175000017500000000444510716352223020626 0ustar pabspabs#include "blowUp.h" #include void blowupOntoScreen( Uint32 *inImage, int inWidth, int inHeight, int inBlowFactor, SDL_Surface *inScreen ) { int newWidth = inBlowFactor * inWidth; int newHeight = inBlowFactor * inHeight; int yOffset = ( inScreen->h - newHeight ) / 2; int xOffset = ( inScreen->w - newWidth ) / 2; // pitch is in bytes // convert to width in pixels int scanlineWidth = inScreen->pitch / 4; Uint32 *pixels = (Uint32 *)( inScreen->pixels ); // looping across the smaller image, instead of across the larger screen, // was discovered using the profiler. // an entire screen row is repeated inBlowFactor times down the screen // (as a row of pixel boxes) // Thus, we can offload a lot more work onto memcpy if we assemble one // of these rows and then memcpy it onto the screen inBlowFactor times for( int y=0; yp?jSG ׆ 88J>JL20|Kt<#"]2Nw8*VeFeYCn>z*:~[Z,'IENDB`passage-4+dfsg1.orig/gamma256/gameSource/Makefile.GnuLinux0000640000175000017500000000024311375557230022061 0ustar pabspabsPLATFORM_PATH = linux PLATFORM_NAME = Linux TIME_PLATFORM_PATH = unix TIME_PLATFORM_NAME = Unix PLATFORM_COMPILE_FLAGS = PLATFORM_LINK_FLAGS = -lSDL -lpthread passage-4+dfsg1.orig/gamma256/gameSource/HashTable.h0000640000175000017500000000504610711176713020657 0ustar pabspabstemplate class HashTable { public: HashTable( int inSize ); ~HashTable(); Type lookup( int inKeyA, int inKeyB, char *outFound ); void insert( int inKeyA, int inKeyB, Type inItem ); // flush all entries from table void clear(); private: int mSize; Type *mTable; char *mSetFlags; int *mKeysA; int *mKeysB; int mHitCount; int mMissCount; int computeHash( int inKeyA, int inKeyB ); }; // Wow... never new that template function implementations must be in the // same file as the declaration template HashTable::HashTable( int inSize ) : mSize( inSize ), mTable( new Type[ inSize ] ), mSetFlags( new char[ inSize ] ), mKeysA( new int[ inSize ] ), mKeysB( new int[ inSize ] ), mHitCount( 0 ), mMissCount( 0 ) { clear(); } #include template HashTable::~HashTable() { delete [] mTable; delete [] mSetFlags; delete [] mKeysA; delete [] mKeysB; printf( "%d hits, %d misses, %f hit ratio\n", mHitCount, mMissCount, mHitCount / (double)( mHitCount + mMissCount ) ); } template inline int HashTable::computeHash( int inKeyA, int inKeyB ) { int hashKey = ( inKeyA * 734727 + inKeyB * 263474 ) % mSize; if( hashKey < 0 ) { hashKey += mSize; } return hashKey; } template Type HashTable::lookup( int inKeyA, int inKeyB, char *outFound ) { int hashKey = computeHash( inKeyA, inKeyB ); if( mSetFlags[ hashKey ] && mKeysA[ hashKey ] == inKeyA && mKeysB[ hashKey ] == inKeyB ) { // hit mHitCount ++; *outFound = true; } else { // miss mMissCount ++; *outFound = false; } return mTable[ hashKey ]; } template void HashTable::insert( int inKeyA, int inKeyB, Type inItem ) { int hashKey = computeHash( inKeyA, inKeyB ); mSetFlags[ hashKey ] = true; mKeysA[ hashKey ] = inKeyA; mKeysB[ hashKey ] = inKeyB; mTable[ hashKey ] = inItem; } template void HashTable::clear() { for( int i=0; ia[\0<#&q50_ } 7OjJeR0\:ϝ;7cƌFb'Mx޼<6zYΌ5}=_{mZd{4rFG/>}JSf@#z8*Ğ4?f3m> nJuc{0B{Ǯ#}t暈뺲TB<&ۓE~qlmm5ܫyl7'msWVׯ[aRf@`{g{Z} P{r|*QC΍?{dlsMe-˲[e˲,"h&͋b?y2y뺵[[+pҦQBpw{U^wKx>KRQ( !?ժzD !.\{~``s^]S{/OmuvcdaRH)9qc}KK l\9%Bay}Jsx [[fVzV܌ҳ|3J~kq#pŞ=+`X>}L4ǶU`۲>c18sVwqwf /}ՐF wUZA&#og &/} +7rO}ӣx{>~ 7Q@ᇟSs ˢ/un{㸙hs@ja/ 7 Oq$tرօZ~P_BrjNh3O=<•a4'toڷ/I?'+`uEm ߸7X] >x0i3ƤtcGk׮yt[wǃ5p)uرVmDzj[9o1qgg=9ӧbKӾ},4V)^\7=1ha_ӶhgtB !crq2՟1i 0n4.;5WY/\?O+p۾z݈7~zoE k*m` PJcP.^=}*S-_mRf kz' ڜHO~7W6=;)񳅭g}JU^uJr{b#?v0nk)'?K2cPpJb A<͑T]}ӣ?s{IU1q(w}*  Avwd3+[=3 \YW7Vh8E3?gwm̙3?_5kT7oάY{?mtӷV g/Z$+ p0qup﷯rY1Z~ۧ'}ߧW˖Çiݻr[nظqcTW)߰leYɼlU~9+=پeS0(gќiLteK_8˂?uٞ=u)?d *qdh>͏YY&8 G>NUNU~|mo}X>8bbzpuɲSug,U\Uotniϻka?⼢BozW3ߘ1- } h7mˎ|sԳk׮kM>/m9\9ΜSb3 aÔ3EX.P+Ty@Z}>N UjYYK7οę ҿQupA>gX:{/mu?^ϣ՝?ZRHf;s}_ ۑX0>J,ۃJ1nsO_(= |m{3@wNf>~Xyx{- `UyUz.,fO}(m{O-7m:D~ԩ.ӳ-"kk-;o`;AçpS /}_}^1@=<Qp_};775Jak GXb`Q^Y}zs":E_P@T AoB(~۝ >Zzg 9KMAWm9cv %qf= ف J.<, !?~؀ ;@x.>Fb@ZF0f} d )COUtRgd 'M}tu-2};dp>^FQ7}Da[xL}w늭²0}}|şa+Zv}~y,[a@K`2=}$ ??ܰ+HHT?W aVgGOVyp72OA_ Q \ zՁo:.h3l O"3#-\\Gy7Qscg֮ʂt}q 䣊BU>@>1G}b4`9`/wOBI?i3qǮ;3 y`ݺٲs}^>KPK1ݳ)KYg^nn{{늭up ,*B)JR_?oPO|_P_}B|'M>6o}⛜Vm۴߷$gJs1`u vp/ыlLy,x}XJq @BIP1P_ >l7|Nt؇_}[PAa ׏lO1ފI]j>%Oz>y#ׇk" t|~"aq96} YHI) A~WӰz4zlڢQE^Hd>0BVgdA&-CC׮?)Ϧ?+%3}$~I#p]sJt ydk 5G;K{zhl(ǷjWllaYvjd{>ea5j}͙ߜO?[?b't޹m#)YC[BHNl~$g5$/m ~{YhAVxҷ%埙F 0P=,#ƙ}">b$X4[wʭ:EsGۇp_NrAlQ{? yR@R/Mؽ.vSn%jk!7>D XcM>P q5 7Ub}Eҗnٷ|e_g }IыSlKlN⇶S Y.b9yE*̱uG`~9E /Z:^9va,BԃZY{˿8bF׽Z:ǜG> % 8%K~FF/ggih1P r**#7_!jT`*ç>+'A~}uGb =8PxPȑ?ȏ >'Xegr*܂pwy>)V2QE1`}Ǣ9Tݏ/ ||\G8.'G}05b|d$~)axFyU > `@:ɿf|wCE^95睁}b .>F= V_g%j#) kGskW9*mObDq$*+Cu 4>>S>5Es?k[,mc_ XehG*UodEGg(C}Ývӓ>@շ!\ !}QG$6ē2-ڲsjPyJΞ@ծ۱m]h3~ofm)g}.m@Ctk&J'o_'h -$AUXB7jɐ2\']jΩy̰Ϟׇ9* }˻OPBq8~=C=y} L~"Sm_^)9aкt؇ƜSto >!Gky~{RrJkZY$AΝ{wow&c|2!h?t_)1@PgSۋڷz4O='>IIg='ϟ^<yf@Ӱm-mSKǗ}'AWWhЛ.4)g>񥽟@!7~q9ꧽR ' ؇0=@}:{,WI)jf'3>=C$ d}j J3ctIO0q-k`}DH tt{K{}3>(R}wsh~l{}U}FC$>>$Bפ/tOmҷ*lX!CfH>}xJao'$5},h mH_%'J?qҿ )t=Om{ۧwvRG71F9}27f: m«M7)\T^88g߁[?]GxJUc+k]v-CU'7nDNůwuM47R]V/\OyE^T槊=>\+X s?, [seIICOxihj`Dj=U?6;usyt/jX'y}Wltmf@L'Gί,}V~:ԨP> ?$H^[눑ы;J]aO>߻5p]Nfݔ}'|txƥ=Ds=uzRp\ 7{]OGx6>)o20AKi;Б]}ݭ}:V/;#@<> 4A:@ʉ_饴}r/madXR4_c&a&mzO@3ԓ ۇvM|a`JO 죅~)cɴ=l復B^C_mD՝Ijf@8WL6'~&m49I:#zBǾ9} I}=Gz:W77ΰ6n$> 'sʈ>"U`y׏}ZFǜՓt*^ md◤|suq(0#X~@G̎ z>%E3}t~_yc9}zfCF*?9U}CS߬W@/>ΞJ_85&uSWD觮#u^I3d ^E` 5qE^ 32zq DnWZu|siԇ}ϒd-li(>)\цSgA9}㪬8? ڊhQUD!m3g$oժ8IY/!اCއ햍 >1(SK>O۷mKzIʫr]9i?ij.1m3j!?QJ>z@p5qmmE޵ܾ7p'tIDATC>*>T!_yCOtmHA\t(y㜓Opi >o2C=ʬLO^*t^!?aqGfK'<+˪#y*{ 1᫔dO¶_>WBkg>M?|UH/!BeO?wq35ˈR7W >˖]}Zr,9sOn􍶇I3sV~@[B |1-|MuU&Q_;y+`ZsgjYJyluUjzH+{mD죎y|w~jE4/zG=^F-o p%ϡ{<eL y{UO:q@rC=}WN˿8/N_PE:G2(_֔gJRv _y9_A=ܶڸSe]**7/_xrnIiބmcAjJ ʇО=:eǶ)I:%ۻc~ms53@w'~73{wcwMJvJ-ܯR2C-ƌlG09/8c][K{Nh b>č>ҴIۧd"OTɺh }iXse+y=zԘٶ8Gix3n>Ԭ &d9jOAk|{LCiQg(SJ4LAĈޯ}3>9萗=}p@\IߩW͛u篖-3Oltvo//+fxG|94'a{cFR=+s)$[#=C>},f/Q?%NRn8&D1yut( 8A m{9=xD<Š]?cy 2W?S nϋ;d/}|K}Ynاß^DW7"ď q?QG}];{?y4kg,UeZN^˖wp=f_}>?C#CVI@̟+Z#FG8շ 1'ۨ%Ƚwdb Iz3S;˭s= tV/xwP<$#]յ!;B(/]!g1_zHE^?FEFi%"{>S: lu&h[?aڹ|I#떍l 0}kV8B:xgL'xA' cOPn۲aنzM㶯G y&!+#{PYy@2KvpG29ݖ+:yN'?s^}cG=gF (h OgGbi+ĵ.T|׫|%~e`H}Ers$,KB̞SGO_3}J쩾by<[Zg|ϧn*Õti'##;I"x)k3:8 o'ڵkwܩ}T}ȋ.lÆܲAUΞJUxJy)ou_3ZQ]1`h i1|M{'ګm4uc6ͰX9\ /}ͷ N,m Ϩ`@Lmq"Q%;`'$~hGuoT؟Q?AXsO>+%'3@ O)_ s]W;}:06кPDIa!/Im_Iz- ھ_~O 2D?+}{X Ey%= >v!m#ۇ}Ju@Ertأw"m#ҥK~ռb>FF;ۇyUY/}]ۇYuT]ۧ竽?]!m$Slmm" u+y}0 qYTǫm`T?r~?>emQC.!A\Ro7}'[t>3S\UT?utȑ>zyr2OȆ&*M/I2˟ ab.Jܑ\a‚M>ao]_QC_'$Ut'tOE\ћThU畹}I:/sO95pD0J:Obxy te>jI $ {s5\c}y!vS@쩄C3iNYs$|( ٿC^ϵr2Yp'g3}J=G]L#Ce !rS >>`y ƾ}9]*kTN"Sga_;-Sqt*79a"g }e>f؇n찟EabzŐafsik+]?ɞ}د>oDpX߈6&TG'zJ4>W@ۇZw)۟8O'۬#>Ʈp+kTC˧S/ G=OF/}ѣFcT|'mʠHgϾnYK~\Qm: ^@&e4N 4%aGYOrNotSBW?lhX%A5~|,Bx3y]GO9%F2dGmP`/!a!gd" r~3Y~Ge^v%D:?L_NmrN^9}bOڇVWQ%Q<]-dr~#E^ k+eVTӟ2U>ueo(?[~>l=sR$ծ?EGnw>d;>K?#zGOm `;PĜi̙>8 7G_>N)E^_ٷo.QyRrKJn)_N)hCûIۇ$6#OE^.m'P\֦?|>~x@wh4ќOʓr4ڧf~TP `ܴjGCa[(ZvKЯSѼ؃"AK]ۇFHlyƨ3+v":yqs |rk$=M[F ?0(It` >he_N>sjJ slS(ٵ>$}b_NB{>+tteg,OD* ul'3}6s"X~TIiv T@Mۇ~''蛳7SGx^Jҙ~:{*>9 ӌ@ѻcyGsܰ_ utO}h5Bziy7on͗܀j`K"Q2=4tÇaޟ#f@0e:y5o{hs 򯁵7KYL:Cau>ɑoG#`*OC|r{H- Q=IIWMOU %>>c1>MGߜOy|t!_yuTY d$}@;y5]Tw6a ܕdw? ~@?>F&`4pWI?U'cKӧ+Ƥ?xZuGKGXS:o|l9Gq6Hpќi+s])׬5pO>+\Pyr 4]o`xhۇE~m=Gm[nt~m;7Cֈt"͹f}Ʋ#$>zwDgjuSrJ_Tҹϱ\R_K-y۬=>PX65{wq@ܥ*Ht;m?+#* eQbOWhJex*۹k:knPKdLK>*ѧ]-;c}p-J:{B?^ {`K{zxj{9K?6FGގ!j%h.}C"?9):GcO#@)}}h@@gk[@bݙ|%g@LYz @X(DU>cdz}D #&U*q}i~݇jS8QT}2AXدG Q2  W|7Ol$.'IENDB`passage-4+dfsg1.orig/gamma256/gameSource/musicPlayer.cpp0000640000175000017500000004333111376314017021652 0ustar pabspabs #include "common.h" #include "Timbre.h" #include "Envelope.h" #include "minorGems/util/SimpleVector.h" #include #include #include #include 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 = 4; Timbre *musicTimbres[ 4 ]; int numEnvelopes = 4; Envelope *musicEnvelopes[ 4 ]; 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; 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.6 * loudnessPerTimbre, keyFrequency, heightPerTimbre, sawWave ); musicTimbres[1] = new Timbre( sampleRate, loudnessPerTimbre, keyFrequency, heightPerTimbre, sin ); musicTimbres[2] = new Timbre( sampleRate, 0.4 * loudnessPerTimbre, keyFrequency / 4, heightPerTimbre, squareWave ); musicTimbres[3] = new Timbre( sampleRate, 0.75 * loudnessPerTimbre, keyFrequency / 4, heightPerTimbre, smoothedWhiteNoise ); // 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.05, 0.7, 0.25, 0.1, maxNoteLength, gridStepDurationInSamples ); musicEnvelopes[1] = new Envelope( 0.1, 0.9, 0.0, 0.0, maxNoteLength, gridStepDurationInSamples ); musicEnvelopes[2] = new Envelope( 0.25, 0.0, 1.0, 0.1, maxNoteLength, gridStepDurationInSamples ); musicEnvelopes[3] = new Envelope( 0.0, 0.2, 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; y4hI9fbҸ\IENDB`passage-4+dfsg1.orig/gamma256/gameSource/musicPlayer.h0000640000175000017500000000050711376314017021315 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(); passage-4+dfsg1.orig/gamma256/gameSource/World.h0000640000175000017500000000174011121533201020071 0ustar pabspabs#include typedef uint32_t Uint32; // these can be called once at beginning and end of app execution // since loaded graphics can be reused for multiple games void loadWorldGraphics(); void destroyWorldGraphics(); // these should be called at the beginning and end of each new game void initWorld(); void destroyWorld(); Uint32 sampleFromWorld( int inX, int inY, double inWeight = 1.0 ); void startPrizeAnimation( int inX, int inY ); void startDustAnimation( int inX, int inY ); void setPlayerPosition( int inX, int inY ); void setPlayerSpriteFrame( int inFrame ); void getSpousePosition( int *outX, int *outY ); char haveMetSpouse(); void meetSpouse(); void startHeartAnimation( int inX, int inY ); void diePlayer(); void dieSpouse(); char isSpouseDead(); char isPlayerDead(); // age in range 0..1 void setCharacterAges( double inAge ); // push animations forward one step void stepAnimations(); int getTileWidth(); int getTileHeight(); passage-4+dfsg1.orig/gamma256/gameSource/blowUp.h0000640000175000017500000000043210727277424020276 0ustar pabspabs #include #include /** * Blows an image up onto the screen using nearest neighbor (pixelated) * interpolation. */ void blowupOntoScreen( Uint32 *inImage, int inWidth, int inHeight, int inBlowFactor, SDL_Surface *inScreen ); passage-4+dfsg1.orig/gamma256/gameSource/spouseSprite.png0000640000175000017500000000210110710626105022045 0ustar pabspabsPNG  IHDRPIDATX1KAZh!2f6K32H}`|»bSL :pgRHTZ\wnlxR8ܾo)!5'!"|w]_nGr;ҔӡQ%wV?֟nKj%w\> ?m 2,'K;1 טhd+@9iLԈ.X"J$`pǼ{d;bR+jc%\mXwdxn5f;dm* `g4 ŝqAAj[+g~6Fİ69kHVpuV cLD$u8Y1K6.$@166 bl؉ZcJQ1xJQ i^"xċ/5#E)vSbrOYY )"n}%0i%Vic X &;N'9{ę DNF䄈[Gqk y fY'O0~HVxu 3,$ 8xSŻ?KĘ_TSSS^]Twv]Ý1O=W6b28zq?IENDB`passage-4+dfsg1.orig/gamma256/gameSource/landscape.h0000640000175000017500000000675010706226004020752 0ustar pabspabs #ifndef LANDSCAPE_INCLUDED #define LANDSCAPE_INCLUDED /** * Gets height samples from an "infinite" fractal landscape. * The landscape can change over time by varying t. * * @param x the x coordinate of the sample. * @param y the y coordinate of the sample. * @param t the time of the sample. * @param baseFrequency the frequency to use for the lowest detail component. * @param inRoughness the roughness of the landscape (how much high frequencies * are factored in). Should be in the range [0..1] with 0 making a very * smooth landscape and 1 making a very rough landscape. * @param detail the detail level. Larger numbers result in more * detail. Defaults to 10. * * @return the height of the landscape at the sample point/time. */ double landscape( double inX, double inY, double inT, double inBaseFrequency, double inRoughness, int inDetail = 10 ); /** * Samples height of a landscape that varies in roughness over the xy plane. * * @params same as for landscape, except: * @param inRoughnessChangeFrequency the rate at which roughness changes * over space. Should, in general, be less than inBaseFrequency. * @param inMinRoughness the minimum roughness value, in the range [0..1]. * @param inMaxRoughness the maximum roughness value, in the range [0..1]. * * @return same as for landscape. */ double variableRoughnessLandscape( double inX, double inY, double inT, double inBaseFrequency, double inRoughnessChangeFrequency, double inMinRoughness, double inMaxRoughness, int inDetail ); /** * Computes linearly-blended random values in the range [-1..1] from a * 4d parameterized noise space. * * @param x, y, z, t the 4d floating-point coordinates. * * @return a blended random value in the range [-1..1]. */ double noise4d( double x, double y, double z, double t ); /** * Computes linearly-blended random values in the range [-1..1] from a * 4d parameterized noise space (keeping one dimension constant). * * Should be faster than noise4D. * * @param x, y, z the 3d floating-point coordinates. * * @return a blended random value in the range [-1..1]. */ double noise3d( double x, double y, double z ); /** * Gets a set of randomly-chosen (though stable) points in a given * region of the landscape. * * @param inStartX, inEndX the x region. * @param inStartY, inEndY the y region. * @param inT the time. * @param inSampleStepSize the step size in the sample grid. * Higher values are faster but result in sparser distributions of points. * @param inDensity the density of points, in the range [0,1]. * @param outXCoordinates pointer to where array of x coordinates should * be returned. Array must be destroyed by caller. * @param outYCoordinates pointer to where array of x coordinates should * be returned. Array must be destroyed by caller. * * @return the number of points (the length of outXCoordinates). */ int getRandomPoints( double inStartX, double inEndX, double inStartY, double inEndY, double inT, double inSampleStepSize, double inDensity, double **outXCoordinates, double **outYCoordinates ); #endif passage-4+dfsg1.orig/gamma256/gameSource/map.cpp0000640000175000017500000001636711124744073020143 0ustar pabspabs#include "map.h" #include "landscape.h" #include "minorGems/util/SimpleVector.h" #include int seed = time( NULL ); //int seed = 10; extern int tileH; extern int tileW; char isBlockedGrid( int inGridX, int inGridY, char inDoNotRecurse ); char isBlockedGridHash( int inGridX, int inGridY, char inDoNotRecurse ); char allNeighborsBlocked( int inGridX, int inGridY ) { if( ! isBlockedGridHash( inGridX, inGridY - 1, true ) ) { // top return false; } if( ! isBlockedGridHash( inGridX + 1, inGridY, true ) ) { // right return false; } if( ! isBlockedGridHash( inGridX, inGridY + 1, true ) ) { // bottom return false; } if( ! isBlockedGridHash( inGridX - 1, inGridY, true ) ) { // left return false; } // all neighbors blocked return true; } #include "HashTable.h" HashTable blockedHashTable( 3000 ); char isBlockedGridHash( int inGridX, int inGridY, char inDoNotRecurse ) { char found; char blocked = blockedHashTable.lookup( inGridX, inGridY, &found ); if( found ) { return blocked; } // else not found // call real function to get result blocked = isBlockedGrid( inGridX, inGridY, inDoNotRecurse ); // only insert result if we called the full recursive version of // inBlockGrid. Otherwise, we aren't getting the real result back // so we shouldn't be tracking it in our table if( ! inDoNotRecurse ) { blockedHashTable.insert( inGridX, inGridY, blocked ); } return blocked; } char isBlocked( int inX, int inY ) { // reduce to grid coordinates int gridX = inX / tileW; int gridY = inY / tileH; // try hash first return isBlockedGridHash( gridX, gridY, false ); } char isBlockedGrid( int inGridX, int inGridY, char inDoNotRecurse ) { // wall along far left and top if( inGridX <=0 || inGridY <= 0 ) { return true; } // empty passage at top if( inGridY <= 1 ) { return false; } // make a grid of empty spaces from which blocks can be // removed below to make a maze if( inGridX % 2 != 0 && inGridY % 2 != 0 ) { // however, if all neighbors are blocked, this should // be blocked too if( !inDoNotRecurse ) { return allNeighborsBlocked( inGridX, inGridY ); } else { // non-recursive mode return false; } } // blocks get denser as y increases double threshold = 1 - inGridY / 20.0; double randValue = noise3d( inGridX, inGridY, seed ); char returnValue = randValue > threshold; if( returnValue ) { return true; } else { // not blocked // should be blocked if all neighbors are blocked if( !inDoNotRecurse ) { return allNeighborsBlocked( inGridX, inGridY ); } else { // non-recursive mode return false; } } } struct pairStruct { int x; int y; }; typedef struct pairStruct pair; SimpleVector openedChests; char isChest( int inX, int inY ) { // reduce to grid coordinates int gridX = inX / tileW; int gridY = inY / tileH; // chests get denser as y increases // no chests where gridY < 5 // even less dense than blocks double threshold = 1 - ( gridY - 5 ) / 200.0; // use different seed than for blocks double randValue = noise3d( 73642 * gridX, 283277 * gridY, seed * 987423 ); char returnValue = randValue > threshold; if( returnValue ) { // make sure it's not opened already for( int i=0; ix == gridX && p->y == gridY ) { return CHEST_OPEN; } } return CHEST_CLOSED; } else { return CHEST_NONE; } } unsigned char getChestCode( int inX, int inY ) { // reduce to grid coordinates int gridX = inX / tileW; int gridY = inY / tileH; // use different seed double randValue = noise3d( 37462 * gridX, 1747 * gridY, seed * 3748147 ); /* Note: Original versions of Passage (up to v3 for Mac/PC/Unix) contained a bug. This was the original code: // use it to fill first 6 binary digits return (unsigned char)( randValue * 15 ) & 0x3F; Note two things: 1. That randValue is *signed* (and can be negative), so casting it to an uchar is a weird thing to do. 2. That we're only multiplying randValue by 15, which only fills the first 4 binary digits (there used to be only 4 gems). Thus, if randValue is actually *positive* between 0 and 1, only the first 4 gems have a chance of being activated. What this code should have done was convert randValue to the range [0..1] first and then multiply it by 63 (to convert it to a 6-bit random binary string). However, this code *seems* to work, anyway, since 2's compliment was being invoked to handle casting of negative randValues, so all 6 gems were sometimes being activated. However, the 6-bit gem strings were always of the form 00XXXX or 11XXXX (where XXXX is a random 4-bit sting) due to the 2's compliment and the fact that the negative numbers being complimented were never less than -15. So, 2 of the gems were tied together in their on/off status, essentially turning 6 gems into 5. The problem appeared on platforms (like iPhone) that don't preserve 2's compliment bits when doing signed to unsigned casting. On these platforms, all negative numbers were being casted to 0 when turned to uchars. Thus, half the treasure chests, on average, had no gems at all. Of course, a proper fix, as described above, would go beyond just making it work on these platforms, but would also change the behavior of the game (those last two gems would no longer be tied together in their on-off status). After much deliberation, I came to the following solution: The following code emulates 2's compliment casting, whether the platform does it or not, making behavior on all platforms identical. (And preserving the original bug!!) */ unsigned char castedChar; if( randValue < 0 ) { castedChar = (unsigned char)( 256 + (char)( randValue * 15 ) ); } else { castedChar = (unsigned char)( randValue * 15 ); } return castedChar & 0x3F; } void getChestCenter( int inX, int inY, int *outCenterX, int *outCenterY ) { int gridX = inX / tileW; int gridY = inY / tileH; *outCenterX = gridX * tileW + tileW / 2; *outCenterY = gridY * tileH + tileH / 2; } void openChest( int inX, int inY ) { pair p; // reduce to grid coordinates p.x = inX / tileW; p.y = inY / tileH; openedChests.push_back( p ); } void resetMap() { // new seed seed = time( NULL ); //seed = 10; openedChests.deleteAll(); blockedHashTable.clear(); } passage-4+dfsg1.orig/gamma256/gameSource/common.h0000640000175000017500000000041611376314017020307 0ustar pabspabs#ifndef COMMON_INCLUDED #define COMMON_INCLUDED #include "minorGems/graphics/Image.h" // reads a TGA file from the default ("graphics") folder Image *readTGA( const char *inFileName ); Image *readTGA( const char *inFolderName, const char *inFileName ); #endif passage-4+dfsg1.orig/gamma256/gameSource/music.png0000640000175000017500000000237510716061761020504 0ustar pabspabsPNG  IHDR WSiIDATxq@%R>*A,"?`<̓fl4XIJ?~X{rY"q_ p'˶c0n `8׷!l;+CW#f jG/Cۄgg9f jtqʘ3=+ [-P:뛟z_}Σ%qdy` '$vӚJ<~Kaæک97$ L,Jҏ_3)5.o q_kU8ϊt̏.`1[%3wK]4FOaF]Q yRwi; gH׷_J@枟W_O.AuK9~75)w4KlR s6 _W^zI~)gMdݓXhV9zNLݓ$_ ?ln-ȫ @ pGиc-/h-*\phs~ ;YKrOSd chc|Msȁs0=ihR!i<.~.G]"%&K;mg|w62t\~~M8kAx (q/Q~Կ)?>ZW?G oCY zK~ԏ/)/cm1P?czzzzzmw\C_9f(k8SAݶ3>W_/`׶qՏQ#  u6e@1G4{>nzzzzzA @ 9@.OeiQ?pf cg..?ЀYZ nlic?36r&4u?6 m_mv>MP ` ` &CB"5CMOOOO9@!`z<ȅ6;zzzzzmB00hSB====6e@! `!}~釁~ ܘzInRgпOvBoS~IENDB`passage-4+dfsg1.orig/gamma256/gameSource/Makefile.MacOSX0000640000175000017500000000037010716122113021365 0ustar pabspabsPLATFORM_PATH = linux PLATFORM_NAME = Linux TIME_PLATFORM_PATH = unix TIME_PLATFORM_NAME = Unix PLATFORM_COMPILE_FLAGS = -DBSD -D__mac__ # need to compile and link SDLMain.m PLATFORM_LINK_FLAGS = -framework SDL -framework Cocoa mac/SDLMain.m passage-4+dfsg1.orig/gamma256/gameSource/testNoise.cpp0000640000175000017500000000257411124744464021342 0ustar pabspabs#include "landscape.h" #include void printBinary( unsigned char inVal ) { for( int b=7; b>=0; b-- ) { if( ( inVal >> b ) & 0x01 == 1 ) { printf( "1" ); } else { printf( "0" ); } } } int main() { int numAllZeroOrig = 0; int numAllZeroNew = 0; for( int i=0; i<20; i++ ) { double value = noise3d( 37462 * i, 1747 * i, i * 3748147 ); printf( "%d ... %f .... ", i, value ); unsigned char castedChar = (unsigned char)( value * 15 ); unsigned char chestVal = (unsigned char)( value * 15 ) & 0x3F; // show in binary printf( "casted char = %d ... original val = ", castedChar ); printBinary( chestVal ); printf( "\n" ); /* if( chestVal == 0 ) { numAllZeroOrig ++; } value += 1; value /= 2; unsigned char newVal = (unsigned char)( value * 63 ) & 0x3F; printf( "\n ... new value = %f .... ", value ); printBinary( newVal ); printf( "\n\n" ); if( newVal == 0 ) { numAllZeroNew ++; } */ } printf( "Num all zero, orig = %d, new = %d \n", numAllZeroOrig, numAllZeroNew ); return 0; } passage-4+dfsg1.orig/gamma256/gameSource/numerals.png0000640000175000017500000000030410706137546021204 0ustar pabspabsPNG  IHDR1NIDATӍ Ҩk-5Pz|$hWksVUߐ@n@`bwXtq 0/ru>9l'L. .i㗫 #include #include "minorGems/util/SimpleVector.h" double landscape( double inX, double inY, double inT, double inBaseFrequency, double inRoughness, int inDetail ) { if( inDetail < 0 ) { return 0.0; } else { // frequency of octave double frequency = inBaseFrequency * pow( 2, inDetail ); double amplitude = pow( inRoughness, inDetail ); return amplitude * noise4d( inX * frequency, inY * frequency, // index different planes of noise inDetail, inT ) + landscape( inX, inY, inT, inBaseFrequency, inRoughness, inDetail - 1 ); } } double variableRoughnessLandscape( double inX, double inY, double inT, double inBaseFrequency, double inRoughnessChangeFrequency, double inMinRoughness, double inMaxRoughness, int inDetail ) { double roughnessFreqX = inX * inRoughnessChangeFrequency; double roughnessFreqY = inY * inRoughnessChangeFrequency; // use low-frequency noise 4d to select landscape roughness // between 0 and 1 double roughness = ( noise4d( 6, roughnessFreqX, roughnessFreqY, inT ) + 1 ) / 2; // move roughness into specified range roughness = roughness * ( inMaxRoughness - inMinRoughness ) + inMinRoughness; return landscape( inX, inY, inT, inBaseFrequency, roughness, inDetail ); } int getRandomPoints( double inStartX, double inEndX, double inStartY, double inEndY, double inT, double inSampleStepSize, double inDensity, double **outXCoordinates, double **outYCoordinates ) { SimpleVector *xCoordinates = new SimpleVector(); SimpleVector *yCoordinates = new SimpleVector(); // discretize startX and start Y so that sample grid for differently-placed // windows always meshes // use ceil to ensure that starting points are always inside the // inStart/inEnd bounds double discretizedStartX = inSampleStepSize * ceil( inStartX / inSampleStepSize ); double discretizedStartY = inSampleStepSize * ceil( inStartY / inSampleStepSize ); // put a point wherever we have a zero-crossing double lastSample = 1; for( double x=discretizedStartX; x<=inEndX; x+=inSampleStepSize ) { for( double y=discretizedStartY; y<=inEndY; y+=inSampleStepSize ) { double landscapeSample = variableRoughnessLandscape( 30 * x + 1000, 30 * y + 1000, inT + 1000, 0.01, 0.001, 0.25, 0.65, 0 ); // shift landscape up to reduce chance of zero-crossing landscapeSample = (1-inDensity) * 0.5 + 0.5 + landscapeSample ; if( landscapeSample < 0 && lastSample >= 0 || landscapeSample >= 0 && landscapeSample < 0 ) { // sign change // hit xCoordinates->push_back( x ); yCoordinates->push_back( y ); } lastSample = landscapeSample; } } *outXCoordinates = xCoordinates->getElementArray(); *outYCoordinates = yCoordinates->getElementArray(); int numPoints = xCoordinates->size(); delete xCoordinates; delete yCoordinates; return numPoints; } /** * Computes a 32-bit random number. * Use linear congruential method. * * @param inSeed the seed to use. */ // this is the readable version of the funcion // it has been turned into a set of macros below inline unsigned int random32_readable( unsigned int inSeed ) { // this is the true hot-spot of the entire landscape function // thus, optimization is warranted. // multiplier = 3141592621 // use hex to avoid warnings //unsigned int multiplier = 0xBB40E62D; //unsigned int increment = 1; // better: // unsigned int multiplier = 196314165 // unsigned int increment = 907633515 // this will automatically be mod-ed by 2^32 because of the limit // of the unsigned int type // return multiplier * inSeed + increment; //return 0xBB40E62D * inSeed + 1; //return 196314165 * inSeed + 907633515; //int n = ( inSeed << 13 ) ^ inSeed; //return n * (n * n * 15731 + 789221) + 1376312589; //const unsigned int Num1 = (inSeed * 0xFEA09B9DU) + 1; //const unsigned int Num2 = ((inSeed * 0xB89C8895U) + 1) >> 16; //return Num1 ^ Num2; /* unsigned int rseed=(inSeed*15064013)^(inSeed*99991+604322121)^(inSeed*45120321)^(inSeed*5034121+13); const unsigned int Num1 = (inSeed * 0xFEA09B9DU) + 1; const unsigned int Num2 = ((inSeed * 0xB89C8895U) + 1) >> 16; rseed *= Num1 ^ Num2; return rseed; */ const unsigned int Num1 = (inSeed * 0xFEA09B9DU) + 1; const unsigned int Num2 = ((inSeed^Num1) * 0x9C129511U) + 1; const unsigned int Num3 = (inSeed * 0x2512CFB8U) + 1; const unsigned int Num4 = ((inSeed^Num3) * 0xB89C8895U) + 1; const unsigned int Num5 = (inSeed * 0x6BF962C1U) + 1; const unsigned int Num6 = ((inSeed^Num5) * 0x4BF962C1U) + 1; return Num2 ^ (Num4 >> 11) ^ (Num6 >> 22); } // faster as a set of macros #define Num1( inSeed ) \ ( ( inSeed * 0xFEA09B9DU ) + 1 ) #define Num2( inSeed ) \ ( ( ( inSeed ^ Num1( inSeed ) ) * 0x9C129511U ) + 1 ) #define Num3( inSeed ) \ ( ( inSeed * 0x2512CFB8U ) + 1 ) #define Num4( inSeed ) \ ( ( ( inSeed ^ Num3( inSeed ) ) * 0xB89C8895U ) + 1 ) #define Num5( inSeed ) \ ( ( inSeed * 0x6BF962C1U ) + 1 ) #define Num6( inSeed ) \ ( ( ( inSeed ^ Num5( inSeed ) ) * 0x4BF962C1U ) + 1 ) #define random32( inSeed ) \ ( Num2( inSeed ) ^ (Num4( inSeed ) >> 11) ^ (Num6( inSeed ) >> 22) ) #define invMaxIntAsDouble 2.32830643708e-10 // 1/(x/2) = 2*(1/x) //double invHalfMaxIntAsDouble = 2 * invMaxIntAsDouble; // 2.32830643708e-10 //+ 2.32830643708e-10 //------------------- // 4.65661287416e-10 #define invHalfMaxIntAsDouble 4.65661287416e-10 #define mixFour( x, y, z, t ) ( x ^ (y * 57) ^ (z * 131) ^ (t * 2383) ) /** * Maps 4d integer coordinates into a [-1..1] noise space. * * @param x, y, z, t the 4d coordinates. * * @return a random value in the range [-1..1] */ // keep readable version around for reference // it has been replaced by a macro below inline double noise4dInt32_readable( unsigned int x, unsigned int y, unsigned int z, unsigned int t ) { //double maxIntAsDouble = 4294967295.0; // modular addition automatic // multiply x, y, z, and t by distinct primes to // avoid correllations. // using xor ( ^ ) here seems to avoid correllations that show // up when using addition. // mix x, y, z, and t unsigned int randomSeed = x ^ y * 57 ^ z * 131 ^ t * 2383; // a random value between 0 and max unsigned int unsigned int randomValue = random32( randomSeed ); // a random value between 0 and 2 double zeroTwoValue = randomValue * invHalfMaxIntAsDouble; // a random value between -1 and 1 return zeroTwoValue - 1; } // noise4dInt32 function call itself was the slowest spot in code // (found with profiler) // turn into a set of macros // matches original parameter format #define noise4dInt32( x, y, z, t ) \ random32( mixFour( x, y, z, t ) ) \ * invHalfMaxIntAsDouble - 1 // problem: now that random32 is a macro, we are passing the unevaluated // expression, ( x ^ (y * 57) ^ (z * 131) ^ (t * 2383) ), down into it. // it is being evaluated 6 times within the depths of the random32 macro // thus, we need to provide a new format where the caller can precompute // the mix for us. This is even faster. #define noise1dInt32( precomputedMix ) \ random32( precomputedMix ) \ * invHalfMaxIntAsDouble - 1 /* * The following functions (blendNoiseNd) do 4d linear interpolation * one dimension at a time. * * The end result is 8 calls to blendNoise1d (and 16 calls to noise4dInt32). * * This method was inspired by the functional implementations---I am * decomposing a complicated problem into sub-problems that are easier * to solve. */ // faster than f * b + (1-f) * a // one less multiply #define linearInterpolation( t, a, b ) ( a + t * ( b - a ) ) /** * Blends 4d discrete (integer-parameter) noise function along one dimension * with 3 fixed integer parameters. */ inline double blendNoise1d( double x, unsigned int y, unsigned int z, unsigned int t ) { double floorX = floor( x ); unsigned int floorIntX = (unsigned int)floorX; if( floorX == x ) { unsigned int precomputedMix = mixFour( floorIntX, y, z, t ); return noise1dInt32( precomputedMix ); } else { unsigned int ceilIntX = floorIntX + 1; // cosine interpolation // from http://freespace.virgin.net/hugo.elias/models/m_perlin.htm double ft = ( x - floorX ) * M_PI; double f = ( 1 - cos( ft ) ) * .5; // need to pre-store intermediate values because noise4dInt32 is a // macro // thus, we end up calling the noise1dInt32 function instead unsigned int precomputedMix = mixFour( floorIntX, y, z, t ); double valueAtFloor = noise1dInt32( precomputedMix ); precomputedMix = mixFour( ceilIntX, y, z, t ); double valueAtCeiling = noise1dInt32( precomputedMix ); return linearInterpolation( f, valueAtFloor, valueAtCeiling ); } } /** * Blends 4d discrete (integer-parameter) noise function along 2 dimensions * with 2 fixed integer parameters. */ double blendNoise2d( double x, double y, unsigned int z, unsigned int t ) { double floorY = floor( y ); unsigned int floorIntY = (unsigned int)floorY; if( floorY == y ) { return blendNoise1d( x, floorIntY, z, t ); } else { unsigned int ceilIntY = floorIntY + 1; // cosine interpolation // from http://freespace.virgin.net/hugo.elias/models/m_perlin.htm double ft = ( y - floorY ) * M_PI; double f = ( 1 - cos( ft ) ) * .5; return ( f ) * blendNoise1d( x, ceilIntY, z, t ) + ( 1 - f ) * blendNoise1d( x, floorIntY, z, t ); } } /** * Blends 4d discrete (integer-parameter) noise function along 3 dimensions * with 1 fixed integer parameters. */ double blendNoise3d( double x, double y, double z, unsigned int t ) { double floorZ = floor( z ); unsigned int floorIntZ = (unsigned int)floorZ; if( floorZ == z ) { return blendNoise2d( x, y, floorIntZ, t ); } else { unsigned int ceilIntZ = floorIntZ + 1; // cosine interpolation // from http://freespace.virgin.net/hugo.elias/models/m_perlin.htm double ft = ( z - floorZ ) * M_PI; double f = ( 1 - cos( ft ) ) * .5; return ( f ) * blendNoise2d( x, y, ceilIntZ, t ) + ( 1 - f ) * blendNoise2d( x, y, floorIntZ, t ); } } /** * Blends 4d discrete (integer-parameter) noise function along 4 dimensions. */ double noise4d( double x, double y, double z, double t ) { double floorT = floor( t ); unsigned int floorIntT = (unsigned int)floorT; if( floorT == t ) { return blendNoise3d( x, y, z, floorIntT ); } else { unsigned int ceilIntT = floorIntT + 1; // cosine interpolation // from http://freespace.virgin.net/hugo.elias/models/m_perlin.htm double ft = ( t - floorT ) * M_PI; double f = ( 1 - cos( ft ) ) * .5; return ( f ) * blendNoise3d( x, y, z, ceilIntT ) + ( 1 - f ) * blendNoise3d( x, y, z, floorIntT ); } } /** * Blends 4d discrete (integer-parameter) noise function along 3 dimensions * to get a 3D noise function. */ double noise3d( double x, double y, double z ) { return blendNoise3d( x, y, z, 0 ); } passage-4+dfsg1.orig/gamma256/gameSource/testMusicPlayer.cpp0000640000175000017500000000117310715122575022512 0ustar pabspabs#include "musicPlayer.h" #include "minorGems/system/Thread.h" #include extern void loadMusicImage( char *inTGAFileName ); extern void audioCallback( void *inUserData, Uint8 *inStream, int inLengthToFill ); int main() { // don't actually start SDL loop, because profiler can't pick // up callbacks (why not?) loadMusicImage( "music.tga" ); int length = 512; Uint8 *fakeStream = new Uint8[ length ]; for( int i=0; i<20000; i++ ) { int x = 5 + 1; x ++; audioCallback( NULL, fakeStream, length ); } } passage-4+dfsg1.orig/gamma256/gameSource/chestPrize.png0000640000175000017500000000071710715634746021512 0ustar pabspabsPNG  IHDRe~DIDATXV1r \l7j=y^֥;A\w\ޣ)rXvTpqhfZUEWʧN0'}x#H?;n0|1BհĮ3bF4ְC>! {tSسMY#Q VO; Rr[ {Cilu.uj/nꡑ"n_eQQpƮXvUQ-#h%(#hhŵBrH),TZ>WE۷!w+L0Q1y(vYR ͳ{F+gBU3854 vk3BBK{p<p! T>wQz(c[*}XYZ{?R\ΨD\_&sz'&DS<YIENDB`passage-4+dfsg1.orig/gamma256/gameSource/Timbre.h0000640000175000017500000000212511122510516020227 0ustar pabspabs#include typedef int16_t Sint16; 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; }; passage-4+dfsg1.orig/gamma256/gameSource/iPhone/0000750000175000017500000000000011376537567020107 5ustar pabspabspassage-4+dfsg1.orig/gamma256/gameSource/iPhone/game.cpp0000640000175000017500000012205311122756143021506 0ustar pabspabs/* * Modification History * * 2007-September-25 Jason Rohrer * Created. */ #include #include #include #include #include #include // for memcpy #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 "blowUp.h" #include "World.h" #include "map.h" #include "score.h" #include "common.h" #include "musicPlayer.h" #include "minorGems/system/Time.h" #include "minorGems/system/Thread.h" #include "minorGems/util/stringUtils.h" #include "minorGems/util/SettingsManager.h" #include "drawIntoScreen.h" // size of game image int width = 100; int height = 12; // area above game image for score int scoreHeight = getScoreHeight(); // size of game image plus scoreboard int totalImageHeight = height + scoreHeight; // size of screen for fullscreen mode int screenWidth = 480; int screenHeight = 320; //int screenWidth = 100; //int screenHeight = 16; // blow-up factor when projecting game onto screen // Max defined by image size vs screen size. // This is the cap for in-game user-directed blowup adjustment. int maxBlowUpFactor; // current blow-up setting int blowUpFactor; // step to take when user hits blowUp key int blowUpStep = -1; // flag to force update of entire screen int blowUpChanged = true; char fullScreen = true; // lock down to 15 fps int lockedFrameRate = 15; // target length of game int gameTime = 5 * 60; //int gameTime = 30; // life time that passes per frame double timeDelta = - ( (double)width / ( gameTime * lockedFrameRate ) ); //double timeDelta = -0.0; Uint32 *gameImage; Uint32 *rotatedGameImage; // the joystick to read from, or NULL if there's no available joystick //SDL_Joystick *joystick; /* // catch an interrupt signal void catch_int(int sig_num) { printf( "Quiting...\n" ); SDL_Quit(); exit( 0 ); signal( SIGINT, catch_int ); } char getKeyDown( int inKeyCode ) { SDL_PumpEvents(); Uint8 *keys = SDL_GetKeyState( NULL ); return keys[ inKeyCode ] == SDL_PRESSED; } char getHatDown( Uint8 inHatPosition ) { if( joystick == NULL ) { return false; } SDL_JoystickUpdate(); Uint8 hatPosition = SDL_JoystickGetHat( joystick, 0 ); if( hatPosition & inHatPosition ) { return true; } else { return false; } } int joyThreshold = 25000; char getJoyPushed( Uint8 inHatPosition ) { Sint16 x = SDL_JoystickGetAxis(joystick, 0); Sint16 y = SDL_JoystickGetAxis(joystick, 1); switch( inHatPosition ) { case SDL_HAT_DOWN: return y > joyThreshold; break; case SDL_HAT_UP: return y < -joyThreshold; break; case SDL_HAT_LEFT: return x < - joyThreshold; break; case SDL_HAT_RIGHT: return x > joyThreshold; break; default: return false; } } // returns true if hit, returns false if user quits before hitting char waitForKeyOrButton() { SDL_Event event; while( true ) { while( SDL_WaitEvent( &event ) ) { switch( event.type ) { case SDL_JOYHATMOTION: case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: case SDL_KEYDOWN: case SDL_KEYUP: return true; break; // watch for quit event case SDL_QUIT: return false; break; default: break; } } } return false; } // flips back buffer onto screen (or updates rect) void flipScreen( SDL_Surface *inScreen ) { // unlock the screen if necessary if( SDL_MUSTLOCK( inScreen ) ) { SDL_UnlockSurface( inScreen ); } if( ( inScreen->flags & SDL_DOUBLEBUF ) == SDL_DOUBLEBUF ) { // need to flip buffer SDL_Flip( inScreen ); } else if( !blowUpChanged ) { // just update center // small area in center that we actually draw in, black around it int yOffset = ( inScreen->h - totalImageHeight * blowUpFactor ) / 2; int xOffset = ( inScreen->w - width * blowUpFactor ) / 2; SDL_UpdateRect( inScreen, xOffset, yOffset, width * blowUpFactor, totalImageHeight * blowUpFactor ); } else { // update the whole thing SDL_UpdateRect( inScreen, 0, 0, inScreen->w, inScreen->h ); // reset flag blowUpChanged = false; } } void lockScreen( SDL_Surface * inScreen ) { // check if we need to lock the screen if( SDL_MUSTLOCK( inScreen ) ) { if( SDL_LockSurface( inScreen ) < 0 ) { printf( "Couldn't lock screen: %s\n", SDL_GetError() ); } } } */ void flipGameImageOntoScreen( Uint32 *inScreen ) { /* if( blowUpChanged && ( inScreen->flags & SDL_DOUBLEBUF ) == SDL_DOUBLEBUF ) { // blow up size has changed, and we are double-buffered // flip onto screen an additional time. // This will cause us to black-out the background in both buffers. lockScreen( inScreen ); // when blow-up factor changes: // clear screen to prepare for next draw, // which will be bigger or smaller SDL_FillRect( inScreen, NULL, 0x00000000 ); blowupOntoScreen( gameImage, width, totalImageHeight, blowUpFactor, inScreen ); flipScreen( inScreen ); } lockScreen( inScreen ); if( blowUpChanged ) { SDL_FillRect( inScreen, NULL, 0x00000000 ); } */ // make rotated version for iPhone for( int y=0; y 0 ) { // open first one by default joystick = SDL_JoystickOpen( 0 ); if( joystick == NULL ) { printf( "Couldn't open joystick 0: %s\n", SDL_GetError() ); } int numHats = SDL_JoystickNumHats( joystick ); if( numHats <= 0 ) { printf( "No d-pad found on joystick\n" ); SDL_JoystickClose( joystick ); joystick = NULL; } } else { joystick = NULL; } #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 ] ); printf( "Mac: app path %s\n", appDirectoryPath ); char *appNamePointer = strstr( appDirectoryPath, "Passage.app" ); if( appNamePointer != NULL ) { // terminate full app path to get parent directory appNamePointer[0] = '\0'; printf( "Mac: changing working dir to %s\n", appDirectoryPath ); chdir( appDirectoryPath ); } delete [] appDirectoryPath; #endif */ // load graphics only once loadWorldGraphics(); // load the iPhone-only arrow graphics Image *arrowsImage = readTGA( "arrows.tga" ); int imagePixelCount = arrowsImage->getWidth() * arrowsImage->getHeight(); double *arrowsRed = new double[ imagePixelCount ]; double *arrowsGreen = new double[ imagePixelCount ]; double *arrowsBlue = new double[ imagePixelCount ]; arrowsARGB = new Uint32[ imagePixelCount ]; for( int i=0; igetChannel(0)[ i ]; arrowsGreen[i] = 255 * arrowsImage->getChannel(1)[ i ]; arrowsBlue[i] = 255 * arrowsImage->getChannel(2)[ i ]; unsigned char r = (unsigned char)( arrowsRed[ i ] ); unsigned char g = (unsigned char)( arrowsGreen[ i ] ); unsigned char b = (unsigned char)( arrowsBlue[ i ] ); // swap r and b on iphone arrowsARGB[i] = b << 16 | g << 8 | r; } delete arrowsImage; setMusicLoudness( 0 ); startMusic( "music.tga" ); startGame(); } void freeScreenDrawer() { endGame(); stopMusic(); destroyWorldGraphics(); delete [] arrowsARGB; /* if( joystick != NULL ) { SDL_JoystickClose( joystick ); } SDL_Quit(); */ //return 0; } char firstTouchHappened = false; char handledFirstTouch = false; char movingLeft = false; char movingRight = false; char movingUp = false; char movingDown = false; float lastOrientationX = 0; float lastOrientationY = 0; float orientationOffsetX = 0; float orientationOffsetY = 0; void setOrientation( float inX, float inY ) { lastOrientationX = inX; lastOrientationY = inY; inX -= orientationOffsetX; inY -= orientationOffsetY; movingLeft = false; movingRight = false; movingUp = false; movingDown = false; if( !handledFirstTouch ) { return; } if( true ) { return; } // old orientation-to-motion code. // didn't work well (mapping continuous value to discrete switch doesn't work well) float threshold = 0.1; char yBigger = true; if( fabs( inX ) > fabs( inY ) ) { yBigger = false; } // landscape, so axises are reversed if( yBigger ) { if( inY < -threshold ) { movingRight = true; } else if( inY > threshold ) { movingLeft = true; } } else { if( inX < -threshold ) { movingDown = true; } else if( inX > threshold ) { movingUp = true; } } } double touchDown = false; float touchX = 0; float touchY = 0; void touchStartPoint( float inX, float inY ) { firstTouchHappened = true; touchDown = true; touchX = inX; touchY = inY; } void touchMovePoint( float inX, float inY ) { touchX = inX; touchY = inY; } void touchEndPoint( float inX, float inY ) { touchDown = false; touchX = inX; touchY = inY; } // variables shared by the 3 functions below: int currentSpriteIndex = 2; double playerX, playerY; double maxPlayerX = 0; int score = 0; // the gem that marks chests containing points int specialGem = time( NULL ) % 4; int exploreScore = 0; int exploreSubPoints = 0; // make sure explore score never goes down int maxExploreScore = 0; int chestScore = 0; // track whether we ever met the spouse // separate from World's haveMetSpouse() char knowSpouse = false; int totalGameImagePixels; double dX = 0; double dY = 0; char done = false; double maxWorldX = 0; double minWorldX = 0; double lastFrameTimeStamp = Time::getCurrentTime(); // use to slow player motion after spouse has died char movingThisFrame = true; Uint32 *titlePixels; int frameCount = 0; unsigned long startTime = time( NULL ); char quit = false; int titleFadeFrame = 0; int numTitleFadeFrames = 200; char stepDX = true; void startGame() { touchDown = false; firstTouchHappened = false; handledFirstTouch = false; currentSpriteIndex = 2; playerX, playerY; maxPlayerX = 0; score = 0; // the gem that marks chests containing points specialGem = time( NULL ) % 4; exploreScore = 0; exploreSubPoints = 0; // make sure explore score never goes down maxExploreScore = 0; chestScore = 0; // track whether we ever met the spouse // separate from World's haveMetSpouse() knowSpouse = false; initWorld(); initScore(); // room at top for score totalGameImagePixels = width * totalImageHeight; gameImage = new Uint32[ totalGameImagePixels ]; rotatedGameImage = new Uint32[ totalGameImagePixels ]; int i; // fill with black for( i=0; igetWidth() * titleImage->getHeight(); double *titleRed = titleImage->getChannel( 0 ); double *titleGreen = titleImage->getChannel( 1 ); double *titleBlue = titleImage->getChannel( 2 ); titlePixels = new Uint32[ numTitlePixels ]; for( int i=0; i floorWidth ) { // slope double slopeValue = ( dX - drawDX - floorWidth ) / ( 1 - floorWidth ); // us trig function to avoid jagged transition from floor to // slope to next floor drawDX += -0.5 * cos( slopeValue * M_PI ) + 0.5; } if( !stepDX ) { // disable smoothed stepping drawDX = dX; } for( int y=0; y maxDistance ) { cappedDistanceFromPlayer = maxDistance; } if( cappedDistanceFromPlayer < -maxDistance ) { cappedDistanceFromPlayer = -maxDistance; } // the world position we will sample from double worldX = x; // zone around player where no x compression happens int noCompressZone = 10; if( trueDistanceFromPlayer > noCompressZone ) { worldX = x + //(width/8) * // use true distance as a factor so that compression // continues at constant rate after we pass capped // distance // otherwise, compression stops after capped distance // Still... constant rate looks weird, so avoid // it by not letting it pass capped distance trueDistanceFromPlayer / 2 * ( pow( tan( ( ( cappedDistanceFromPlayer - noCompressZone ) / (double)( width - noCompressZone ) ) * M_PI / 2 ), 2) ); /* trueDistanceFromPlayer / 2 * ( tan( ( cappedDistanceFromPlayer / (double)( width - 0.5 ) ) * M_PI / 2 ) ); */ // simpler formula // actually, this does not approach 0 as // cappedDistanceFromPlayer approaches 0, so use tan // instead // ( trueDistanceFromPlayer / 2 ) * 100 // / pow( ( width - cappedDistanceFromPlayer ), 1.6 ); } else if( trueDistanceFromPlayer < - noCompressZone ) { worldX = x + //(width/8) * trueDistanceFromPlayer / 2 * ( pow( tan( ( ( - cappedDistanceFromPlayer - noCompressZone ) / (double)( width - noCompressZone ) ) * M_PI / 2 ), 2) ); /* trueDistanceFromPlayer / 2 * ( tan( ( - cappedDistanceFromPlayer / (double)( width - 0.5 ) ) * M_PI / 2 ) ); */ //( trueDistanceFromPlayer / 2 ) * 50 /// ( width + cappedDistanceFromPlayer ); } else { // inside no-compresison zone worldX = x; } //int worldX = x; worldX += drawDX; if( worldX > maxWorldX ) { maxWorldX = worldX; } if( worldX < minWorldX ) { minWorldX = worldX; } int worldY = (int)floor( y + dY ); // linear interpolation of two samples for worldX int intWorldX = (int)floor( worldX ); double bWeight = worldX - intWorldX; double aWeight = 1 - bWeight; Uint32 sampleA = sampleFromWorld( intWorldX, worldY, aWeight ); Uint32 sampleB = sampleFromWorld( intWorldX + 1, worldY, bWeight ); Uint32 combined = sampleB + sampleA; gameImage[ ( y + scoreHeight ) * width + x ] = combined; } } drawScore( gameImage, width, height, score ); if( isPlayerDead() ) { // fade to title screen double titleWeight = titleFadeFrame / (double)( numTitleFadeFrames - 1 ); double gameWeight = 1 - titleWeight; // wipe from left to right during fade int wipePosition = (int)( titleWeight * width ); // fade out music while we do it setMusicLoudness( 1.0 - titleWeight ); for( i=0; i> 16 & 0xFF; unsigned char gameGreen = gamePixel >> 8 & 0xFF; unsigned char gameBlue = gamePixel & 0xFF; Uint32 titlePixel = titlePixels[i]; unsigned char titleRed = titlePixel >> 16 & 0xFF; unsigned char titleGreen = titlePixel >> 8 & 0xFF; unsigned char titleBlue = titlePixel & 0xFF; unsigned char red = (unsigned char)( gameWeight * gameRed + titleWeight * titleRed ); unsigned char green = (unsigned char)( gameWeight * gameGreen + titleWeight * titleGreen ); unsigned char blue = (unsigned char)( gameWeight * gameBlue + titleWeight * titleBlue ); int x = i % width; if( x <= wipePosition ) { gameImage[i] = red << 16 | green << 8 | blue; } } titleFadeFrame ++; if( titleFadeFrame == numTitleFadeFrames ) { done = true; } } flipGameImageOntoScreen( screen ); // next draw arrow icon onto screen and interpret touch to control motion int xPosition = blowUpFactor * 36; int yPosition = inHeight / 2 - ( arrowsH * blowUpFactor / 2 ); int arrowsMiddleX = xPosition + ( arrowsW * blowUpFactor / 2 ); int arrowsMiddleY= inHeight / 2; // touchX is 0..320 // touchY is 0..480 // need to convert these to our screen bitmap size, which is centered on the // 320x480 screen // hard-code blow-up factor for now (4) and offsets to center (24 and 4) int touchXArrowRelative = touchX / 4 + 24 - arrowsMiddleX; int touchYArrowRelative = touchY / 4 + 4 - arrowsMiddleY; movingLeft = false; movingRight = false; movingUp = false; movingDown = false; if( touchDown ) { if( touchYArrowRelative > touchXArrowRelative ) { if( touchYArrowRelative > - touchXArrowRelative ) { movingLeft = true; } else if( touchYArrowRelative < - touchXArrowRelative ) { movingDown = true; } } else if( touchYArrowRelative < touchXArrowRelative ) { if( touchYArrowRelative > - touchXArrowRelative ) { movingUp = true; } else if( touchYArrowRelative < - touchXArrowRelative ) { movingRight = true; } } } int arrowsFrame = 0; if( movingLeft ) { arrowsFrame = 1; } if( movingRight ) { arrowsFrame = 2; } if( movingDown ) { arrowsFrame = 3; } if( movingUp ) { arrowsFrame = 4; } if( ! isPlayerDead() ) { for( int y=0; y 0 ) { //Thread::staticSleep( (int)( extraTime * 1000 ) ); } // start timing next frame lastFrameTimeStamp = Time::getCurrentTime(); int spouseX, spouseY; getSpousePosition( &spouseX, &spouseY ); int moveDelta = 1; if( isPlayerDead() ) { // stop moving moveDelta = 0; } if( knowSpouse && isSpouseDead() ) { // player moves slower // toggle motion on this frame movingThisFrame = ( frameCount % 2 == 0 ); } if( false /*getKeyDown( SDLK_b ) */ ) { // adjust blowup factor blowUpFactor += blowUpStep; if( blowUpFactor > maxBlowUpFactor ) { blowUpStep *= -1; blowUpFactor = maxBlowUpFactor - 1; } if( blowUpFactor < 1 ) { blowUpStep *= -1; blowUpFactor = 2; } if( fullScreen ) { // force redraw of whole screen blowUpChanged = true; } else { // create a new screen using the new size //createScreen(); } } if( false /*getKeyDown( SDLK_f )*/ ) { // toggle fullscreen mode fullScreen = ! fullScreen; // create a new screen surface (and destroy old one) //createScreen(); } if( movingLeft /*getKeyDown( SDLK_LEFT ) || getJoyPushed( SDL_HAT_LEFT )*/ ) { char notBlocked = !isBlocked( (int)( playerX - moveDelta ), (int)playerY ); // spouse and character move, and are blocked, together if( haveMetSpouse() && isBlocked( spouseX - moveDelta, spouseY ) ) { notBlocked = false; } if( movingThisFrame && notBlocked ) { playerX -= moveDelta; if( playerX < 0 ) { // undo playerX += moveDelta; } else { // update screen position dX -= moveDelta; // pick sprite frame based on position in world if( ( (int)playerX / 2 ) % 2 == 0 ) { currentSpriteIndex = 6; } else { currentSpriteIndex = 7; } } } } else if( movingRight /*getKeyDown( SDLK_RIGHT ) || getJoyPushed( SDL_HAT_RIGHT ) */ ) { char notBlocked = !isBlocked( (int)( playerX + moveDelta ), (int)playerY ); // spouse and character move, and are blocked, together if( haveMetSpouse() && isBlocked( spouseX + moveDelta, spouseY ) ) { notBlocked = false; } if( movingThisFrame && notBlocked ) { dX += moveDelta; playerX += moveDelta; // pick sprite frame based on position in world if( ( (int)playerX / 2 ) % 2 == 0 ) { currentSpriteIndex = 3; } else { currentSpriteIndex = 2; } } } else if( movingUp /*getKeyDown( SDLK_UP ) || getJoyPushed( SDL_HAT_UP ) */) { char notBlocked = !isBlocked( (int)playerX, (int)( playerY - moveDelta ) ); // spouse and character move, and are blocked, together if( haveMetSpouse() && isBlocked( spouseX, spouseY - moveDelta ) ) { notBlocked = false; } if( movingThisFrame && notBlocked ) { playerY -= moveDelta; if( playerY < 0 ) { // undo playerY += moveDelta; } else { // update screen position dY -= moveDelta; // pick sprite frame based on position in world if( ( (int)playerY / 2 ) % 2 == 0 ) { currentSpriteIndex = 0; } else { currentSpriteIndex = 1; } } } } else if( movingDown /*getKeyDown( SDLK_DOWN ) || getJoyPushed( SDL_HAT_DOWN )*/ ) { char notBlocked = !isBlocked( (int)playerX, (int)( playerY + moveDelta ) ); // spouse and character move, and are blocked, together if( haveMetSpouse() && isBlocked( spouseX, spouseY + moveDelta ) ) { notBlocked = false; } if( movingThisFrame && notBlocked ) { dY += moveDelta; playerY += moveDelta; // pick sprite frame based on position in world if( ( (int)playerY / 2 ) % 2 == 0 ) { currentSpriteIndex = 5; } else { currentSpriteIndex = 4; } } } setPlayerPosition( (int)playerX, (int)playerY ); setPlayerSpriteFrame( currentSpriteIndex ); // may change after we set player position getSpousePosition( &spouseX, &spouseY ); /* // check for events to quit SDL_Event event; while( SDL_PollEvent(&event) ) { switch( event.type ) { case SDL_KEYDOWN: switch( event.key.keysym.sym ) { case SDLK_q: case SDLK_ESCAPE: done = true; quit = true; break; default: break; } break; case SDL_QUIT: done = true; quit = true; break; default: break; } } */ //t +=0.25; frameCount ++; // other animations run independent of whether player is moving if( frameCount % 6 == 0 ) { stepAnimations(); } if( ! isPlayerDead() ) { // player position on screen inches forward dX += timeDelta; } double age = ( playerX - dX ) / width; setCharacterAges( age ); if( age >= 0.85 ) { dieSpouse(); } if( age >= 0.95 ) { diePlayer(); } if( isChest( (int)playerX, (int)playerY ) == CHEST_CLOSED ) { openChest( (int)playerX, (int)playerY ); int chestX, chestY; getChestCenter( (int)playerX, (int)playerY, &chestX, &chestY ); if( getChestCode( (int)playerX, (int)playerY ) & 0x01 << specialGem ) { // reward player chestScore += 100; startPrizeAnimation( chestX, chestY ); } else { startDustAnimation( chestX, chestY ); } } int distanceFromSpouse = (int) sqrt( pow( spouseX - playerX, 2 ) + pow( spouseY - playerY, 2 ) ); if( ! haveMetSpouse() && ! isSpouseDead() && distanceFromSpouse < 10 ) { meetSpouse(); knowSpouse = true; startHeartAnimation( (int)( ( spouseX - playerX ) / 2 + playerX ), (int)( ( spouseY - playerY ) / 2 + playerY ) - 2 ); } // stop after player has gone off right end of screen if( playerX - dX > width ) { dX = playerX - width; } int exploreDelta = 0; if( playerX > maxPlayerX ) { exploreDelta = (int)( playerX - maxPlayerX ); maxPlayerX = playerX; } int spouseExploreFactor = 2; if( haveMetSpouse() ) { // exploring worth more exploreDelta *= spouseExploreFactor; } exploreSubPoints += exploreDelta; exploreScore = (int)( exploreSubPoints / 10 ); if( haveMetSpouse() ) { // show explore score contribution in jumps exploreScore = ( exploreScore / spouseExploreFactor ) * spouseExploreFactor; // note: // this can cause our score to go down (to the previous // jump) as we transition from not having a spouse to // having one. // we fix this below with maxExploreScore } if( exploreScore < maxExploreScore ) { // don't let it go down from max exploreScore = maxExploreScore; } score = chestScore + exploreScore; if( exploreScore > maxExploreScore ) { maxExploreScore = exploreScore; } } else { endGame(); startGame(); } } void endGame() { unsigned long netTime = time( NULL ) - startTime; double frameRate = frameCount / (double)netTime; printf( "Max world x = %f\n", maxWorldX ); printf( "Min world x = %f\n", minWorldX ); printf( "Frame rate = %f fps (%d frames)\n", frameRate, frameCount ); printf( "Game time = %d:%d\n", (int)netTime / 60, (int)netTime % 60 ); fflush( stdout ); delete [] gameImage; delete [] rotatedGameImage; delete [] titlePixels; destroyWorld(); destroyScore(); /* if( quit ) { return false; } else { return true; } */ } passage-4+dfsg1.orig/gamma256/gameSource/iPhone/blowUp.cpp0000640000175000017500000000543511122756143022051 0ustar pabspabs#include "blowUp.h" #include void blowupOntoScreen( Uint32 *inImage, int inWidth, int inHeight, int inBlowFactor, Uint32 *inScreenPixels, int inScreenWidth, int inScreenHeight ) { int newWidth = inBlowFactor * inWidth; int newHeight = inBlowFactor * inHeight; int yOffset = ( inScreenHeight - newHeight ) / 2; // "up" a bit more on iPhone to make room for touch widget int xOffset = 2 * ( inScreenWidth - newWidth ) / 3; // pitch equals width for iPhone implementation int scanlineWidth = inScreenWidth; Uint32 *pixels = inScreenPixels; // looping across the smaller image, instead of across the larger screen, // was discovered using the profiler. // an entire screen row is repeated inBlowFactor times down the screen // (as a row of pixel boxes) // Thus, we can offload a lot more work onto memcpy if we assemble one // of these rows and then memcpy it onto the screen inBlowFactor times for( int y=0; y> 16) & 0xFF; unsigned char green = (pixelValue >> 8) & 0xFF; unsigned char blue = (pixelValue >> 0) & 0xFF; pixelValue = blue << 16 | green << 8 | red; // spread this pixel across an inBlowFactor-wide box row in // the screen row int boxXStart = inBlowFactor * x; int boxXEnd = boxXStart + inBlowFactor; // make an array to represent one row of this box // we can thus replace the inner loop with a memcpy below for( int i=boxXStart; i #include #include #include #include #include typedef int16_t Sint16; typedef uint8_t Uint8; 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 = 4; Timbre *musicTimbres[ 4 ]; int numEnvelopes = 4; Envelope *musicEnvelopes[ 4 ]; 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; 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.6 * loudnessPerTimbre, keyFrequency, heightPerTimbre, sawWave ); musicTimbres[1] = new Timbre( sampleRate, loudnessPerTimbre, keyFrequency, heightPerTimbre, sin ); musicTimbres[2] = new Timbre( sampleRate, 0.4 * loudnessPerTimbre, keyFrequency / 4, heightPerTimbre, squareWave ); musicTimbres[3] = new Timbre( sampleRate, 0.75 * loudnessPerTimbre, keyFrequency / 4, heightPerTimbre, smoothedWhiteNoise ); // 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.05, 0.7, 0.25, 0.1, maxNoteLength, gridStepDurationInSamples ); musicEnvelopes[1] = new Envelope( 0.1, 0.9, 0.0, 0.0, maxNoteLength, gridStepDurationInSamples ); musicEnvelopes[2] = new Envelope( 0.25, 0.0, 1.0, 0.1, maxNoteLength, gridStepDurationInSamples ); musicEnvelopes[3] = new Envelope( 0.0, 0.2, 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; } } } } } AudioUnit gOutputUnit; OSStatus MyRenderer(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { audioCallback( NULL, (Uint8 *)( ioData->mBuffers[0].mData ), ioData->mBuffers[0].mDataByteSize ); /* RenderSin (sSinWaveFrameCount, inNumberFrames, ioData->mBuffers[0].mData, sSampleRate, sAmplitude, sToneFrequency, sWhichFormat); //we're just going to copy the data into each channel for (UInt32 channel = 1; channel < ioData->mNumberBuffers; channel++) memcpy (ioData->mBuffers[channel].mData, ioData->mBuffers[0].mData, ioData->mBuffers[0].mDataByteSize); sSinWaveFrameCount += inNumberFrames; */ return noErr; } // ________________________________________________________________________________ // // CreateDefaultAU // void CreateDefaultAU() { OSStatus err = noErr; // Open the default output unit AudioComponentDescription desc; desc.componentType = kAudioUnitType_Output; desc.componentSubType = kAudioUnitSubType_RemoteIO; desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; AudioComponent comp = AudioComponentFindNext(NULL, &desc); if (comp == NULL) { printf ("FindNextComponent\n"); return; } err = AudioComponentInstanceNew(comp, &gOutputUnit); if (comp == NULL) { printf ("OpenAComponent=%ld\n", (long int)err); return; } // Set up a callback function to generate output to the output unit AURenderCallbackStruct input; input.inputProc = MyRenderer; input.inputProcRefCon = NULL; err = AudioUnitSetProperty (gOutputUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof(input)); if (err) { printf ("AudioUnitSetProperty-CB=%ld\n", (long int)err); return; } } // ________________________________________________________________________________ // // TestDefaultAU // void TestDefaultAU() { OSStatus err = noErr; // We tell the Output Unit what format we're going to supply data to it // this is necessary if you're providing data through an input callback // AND you want the DefaultOutputUnit to do any format conversions // necessary from your format to the device's format. AudioStreamBasicDescription streamFormat; streamFormat.mSampleRate = sampleRate; streamFormat.mFormatID = kAudioFormatLinearPCM; streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kLinearPCMFormatFlagIsPacked; //| kAudioFormatFlagIsNonInterleaved; streamFormat.mBytesPerPacket = 4; streamFormat.mFramesPerPacket = 1; streamFormat.mBytesPerFrame = 4; streamFormat.mChannelsPerFrame = 2; streamFormat.mBitsPerChannel = 16; printf("Rendering source:\n\t"); printf ("SampleRate=%f,", streamFormat.mSampleRate); printf ("BytesPerPacket=%ld,", (long int)streamFormat.mBytesPerPacket); printf ("FramesPerPacket=%ld,", (long int)streamFormat.mFramesPerPacket); printf ("BytesPerFrame=%ld,", (long int)streamFormat.mBytesPerFrame); printf ("BitsPerChannel=%ld,", (long int)streamFormat.mBitsPerChannel); printf ("ChannelsPerFrame=%ld\n", (long int)streamFormat.mChannelsPerFrame); err = AudioUnitSetProperty ( gOutputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, sizeof(AudioStreamBasicDescription) ); if (err) { printf ("AudioUnitSetProperty-SF=%4.4s, %ld\n", (char*)&err, (long int)err); return; } // Initialize unit err = AudioUnitInitialize(gOutputUnit); if (err) { printf ("AudioUnitInitialize=%ld\n", (long int)err); return; } Float64 outSampleRate; UInt32 size = sizeof(Float64); err = AudioUnitGetProperty (gOutputUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, 0, &outSampleRate, &size); if (err) { printf ("AudioUnitSetProperty-GF=%4.4s, %ld\n", (char*)&err, (long int)err); return; } // Start the rendering // The DefaultOutputUnit will do any format conversions to the format of the default device err = AudioOutputUnitStart (gOutputUnit); if (err) { printf ("AudioOutputUnitStart=%ld\n", (long int)err); return; } // we call the CFRunLoopRunInMode to service any notifications that the audio // system has to deal with //CFRunLoopRunInMode(kCFRunLoopDefaultMode, 2, false); } void CloseDefaultAU () { // Clean up OSStatus err = noErr; err = AudioOutputUnitStop( gOutputUnit ); if (err) { printf ("AudioOutputUnitStop=%ld\n", (long int)err); return; } err = AudioUnitUninitialize (gOutputUnit); if (err) { printf ("AudioUnitUninitialize=%ld\n", (long int)err); return; } AudioComponentInstanceDispose( gOutputUnit ); //CloseComponent(gOutputUnit); } void startMusic( char *inTGAFileName ) { loadMusicImage( inTGAFileName ); CreateDefaultAU(); TestDefaultAU(); } void stopMusic() { CloseDefaultAU(); if( musicImage != NULL ) { delete musicImage; musicImage = NULL; } for( int y=0; y.iAī!ҖzO8\VcVJ)l/@;~7=GP ekyxk.,_˺Ī pDX;`fA~uYCJI+l}7DZSl5EIz&a!:xPv 0>gaq}&]2K6Ɨ[Lkџ2,^~L+S` pHYs   IDATxanWUߟސ@!%"I+V Ċys"~De3X'L7:LɍFM3*H-CM0IHޮ}yιLy^{u{r'OV+HHG`#Ӌ 8lЬ (6&a 4kH&J zaX$@$  `hb AHH`ؠ'E$@lЬ (6&a 4kH&J zaX$@$  `hb AHH`ؠ'E$@lЬ (6&a 4kH&J zaX$@$  `hb AHH`ؠ'E$@lЬ (6&a 4kH&J zaX$@$  `hb AHH`ؠ'E$@lЬ (6&a 4kH&J zaX$@$  `hb AHH`ؠ'E$@lЬ (6&a 4kH&J zaX$@$  `hb AHH`ؠ'E$@lЬ (6&a 4kH&J zaX$@$  `hb \B$@$4Ao~WJA<%5ۥ븰?4PP X mzl`XB  +u-&ZcЖH6#p Qn=w(7)W \vܙX6Ă L`HvG: .y2IHGWv I$@%QfX 9bQ0T eƯe1iIvMsz hi~'A;7%5a}֌G5  , ͔N=l0 qؾh9F~F#at{=u#TC5An-DZSϟK~\3ګZ}SuZ`$3k?JL|!_yes9Yy~0Y]vY_ 7dd$=}ѧ"b$+p`#K/ J񋝬0Z`~?:IEtc*'pGEcま^[=[q׷}[EiXo} Rҗ\=^(uJskMO\'mV'L;Xew=w 佽 `oSV'~EV'OZq <6ihlHE(P4v/Zn4~ WO.~O*ؑV[M! xwPbf͘k>n\LehpLQٷc뭿T,v2nUTZ+^A+,Mjc*'&&nVWb_͠h׭̬zv%{#e:NP=~׽s{y-]cm. 9{mƎѯ!=PBA-y Nv_ZЈ`|vV{8c^Ǯ(#Z1O>6HkV)r=oSS*]BM|luyn8 r 6Uxq_,eۨ>^s<j֪vXhDcVY?}iu~\.aT3J-ݴ5j.`s@Ϝ9Ogǒ6IիϼKΝ>I||0=k^22VV`;4ů+O%}_cSy g/%Ǽ+k66@Y>3\>Ko~yn=>|lMh ygu;[|z<&y,ؿ`#Wl[n9,}wl,oW9jKNY/CgJ;qkkq'wgJa_;(CkS0jk`Æ-p.Zz4a\>=k%|dA#/AyMAmxٻzA3);zNt,pRSLbj"OZ5fa g$x:+3N 62W<&{Q ^ȹUy¡.B1~3Ÿ{u"6^6AYf(W T)̠U?y/iґA*IrA#@0̅u![)(-Bx3,lVх Z΋킳 z ^+Jy-ws\G@^ 4[&cO@3U,NySxG>b/ϣ\wܑ.}W):N'}F+M<'3=N>izH%̽ݯư&Hfs]Cj,=z,y3e(Ʌl4Co{<}7ҽ7_\sMܗp^ / gs\LȋO*w<{QB w }APJϝKEom=cYHYyvMTM>A& 5"Q*YWXλ+aQWgoC +b odz QoY=!M{]_[wi9H3*UW/5p`KPskCfyEY+c_誫^GZ< >aՃ))ăRiS_Z{Oir8' ħtV'ӠQمP' L&|P6+Fxj7t-O6獨xZeæGwDuz2U#>Ĺ/A s^b<fe먉Wgc>hj>S+f7^ o>~Bh4aiaVC;!d].h_~%߾'K_Ipo<*q?r{}jĬSWoA^ICAmnO@* b"UF2":6|pGX)*cJ%c-*(mU@]P Ȝ:;,؛֚jyG=X-8EwvfEjrn7;”tNR)$FȒ*Go^cu(}(05{DfO 1}tAl]Gbƃ?f<92s-hYeF p-6A";co1tWp5?xO2Dk|A#[TL]^LȪBo}6U\/V1 ~/GCڷ|4{'ɿ^L1q]N/2OfA$EΪYnF;h+7e%T!!f!C3_~mxf X٘TDkce1+].6V"W* p7zrA_ƍ1؆o% A-J.Ҫ}جn!x0/N+=ʼnR~+../؛0|͠Ij$qw ZIƬZǏ״)7}G"k݉=wPa"pZVƚՃT'[ v2Ճe[ȰW}CQI 5[~t1J6 ?'r{[w5ky[5 u~"`4y ZSrZµ) '%\n/+"=̵}{P״ jM Rx$Q`W=W&vj\Bp ~:}?EMĀ BIh7ZqAW(_^j W; sakzX<ⰊB<1^A.]}%,8 `<ه8уeyUuw?xh cXB$Bh4Ʈ[`ƕVB&wb_3gg[W+KzKև>hyv5yF9ϝ} ~~ݍZrه'nY[}^IZ]fB?16;4^1ȼ.{+՗{Ow~l翠jvɹs2}пK}]u{/M=W+7a:C}3^T-o_=JU*ʗK[?/zՋ}v!%?>մK.M]NߵCׯŐTC7pZCS1߁iʴU2c. @E޶6=Dz&A~`@w6"ugjՑ^!R 6E /:w8Mkr䦚9p^fmJmǓxD^B&w؝%i4h $V*XyeJjU#ﰁ(兡5B^vS 7Qo:k`X΍\Nf8a~rYk2VKEU4< q ;Oڐ;^K|*@r=N^ٻa͠6]e2 *y!{֡K_M˷nZE{x5)XewZi_lWvS18j"~ RA~4I_ч`/U5s\Tz}Û-7o=o~niK[sWܜvx(#>r?ep!/do:/ j嗧Md8;hejDJ(PS)_!"WDam7pO:]**:*PtUTS*5vXԢ竾[U ߵՀp0XbbE>`X&xtkQ_tg=\[q 4h\i1%#HSyn#dd6ٛC.<=ҐDky+uv{JDSJl! OThJ gMB)mx%jG;lܹp| |E1>Ώs :?i4##Hi֑{W.'XxbiJr+7*F8qB9zc6Ə EPP͝&)5ÕoWAY?t}KhXZCErj9q^ﴱ* ?.[=ț/,Yx*߇;^΢V.\pY%m!n8gӃSZ)?yߟ c_C!TsgTC5؉+~tժqyN?+m}Wo^6^v {u_ZA$~ >]˵oN V.vNub RڵtI=>^y?bj# p>;h^Le%TBR/2,dh`6g3־K1g'VE&VS6uh}Zaehe1vp 3~D;s[؈Pe3V寪}HO_Ls<,2׹ !8jw{]V2(Sp WF(`gDZG* 6f{>(N'~Gbp*?" (<XP|U[.l? v~ykeYf֚!/ 9~'v_R8K{oQ3m㶳1ܜ! NE)~רN.G)N콠h]*wXʁD4SpiVЈP:!Γ[w~ a4N^ckֺ_m$'5D>zQFD(Bګ{~m}}HT֙}Ìf01ic3h{j-)I[^[Q9~;݃^-}{,y3!_>[0a6?]}:Bd)NQ SEemJ+G70l ox ?WhxcMgZ/xՄnku_~Èk8 ưݒ݅ܵSk}m"nsGKa-ѵwqIDATę^=`;*P_vF̃_{3rwo, Gvw wgJa\ڡwjͮAmEi/gTPoe€+%!JXƠwCuRgW}ś'֛hǰx>E vڠ gY,%lҠrAF^` $z2&3_?,@YC| n"ϯǜԋ4z@9 ;-of}3A"yjPa@O"Ocl^Gv}fSZ5 eF\GfVV{FoDWn}D@_Q#z}7K+,.O,Od[L]\3y:%8=u֙؜?V$F!Ay&~ n#ۊh>z&x}Cנ r`N vLzz[烃byB:?@>~|'{xu_3Q:E7pɓM;r4]ZTI&YȖ*Y-ه4xTz񄓖[Ƴ2 =o9oUifzhAw JXo~+ţ\}.J5"UYi4h9v?)!V`8{60h/fZԒ;W :wl!D-R^Ӵj8Tx7{Ȣyy 2yDEU_7l+x}xmW(Z9g:PV[d4Z eu(VuJ@<1Hg͠6Fw~.ﲰA`c A^j xJ<`>y_٩ JE?yPOH޹;?7#k.ڋbȢ` .󦆀ò?(ki>'duWzHI5n?N@&dPT괙e]-9}{=j^ %.nR9>LݹO>@7MLKכ](Z;܉<EbJM?#dlv[pR$,U(M4~\l# \3J^̛k:ky\6)5h!d*pvU-U VYb.J]`G&*ƣF=FW6sW7|h> x1]e{u I>h >0e2]EɩUjT!Ydz$/e  H LGs! `^`yd y`G%  A/0<2 <A#OH`ؠtH`ؠ'FI$@l L:L$0l$X 6&G&6yQ ,# ̃<(IH zIIA zyb$@ $$@ =<1J `^`yd y`G%  A/0<2 <A#OH`ؠtH`ؠ'FI$@l L:L$0l$X 6&G&6yQ ,# ̃<(IH zIIA zyb$@ $$@ =<1J `^`yd y`G%  A/0<2 <A#OH`ؠtH`ؠ'FI$@l L:L$0l$X 6&G&6yQ ,# ̃<(IH zIIA zyb$@ $$@ =<1J `^`yd y`G%  A/0<2 <A#OH`ؠtH`ؠ'FI$@l L:L$0l$X 6&G&6yQ ,# ̃<(IH zIIA zyb$@ $$@ =<1J `^`yd y`G%  A/0<2 <A#OH`ؠtH`ؠ'FI$@l L:L$0l$X 6&G&6yQ ,# ̃<(IH zIIA zyb$@ $$@ =<1J `^`yd y`G%  A/0<2 <A#OH`ؠtH`ؠ'FI$@l L:L$0l$X 6&G&6yQ ,# ̃<(IH zIIA zyb$@ $$@ =<1J `^`yd y`G%  A/0<2 <A#OH`ؠtH`ؠ'FI$@l L:L$0l$X 6&G&6yQ ,# ̃<(IH zIIA zyb$@ $$@ =<1J `^`yd yda2Jh&V=go?9C3";%6,=/A_\\ix_ggHc&zyxOͻ7?K=ctϏ|xsg yaIR"-;rw[bI7(5׵޴?;}Gp6ؠKC.^wjL ؠG ؛6ƹ54 M`B@ cox{}9&{[=g(n nsDݹ펺eˮ..n(Ǯs2vbΕ% `P2l :e}\;8OʝRe9S8g?vrY]׿]KF#gУF @Esν7#Gñ hwښ28,6:;f I)H`[q%[흻EMG5M~=e9>y @'ҝ|g]iq Ϙ;C`][g7N܅:`&s!zs6|.d!ŤzYw|.҆~޸@Mco]] H`|=U܈/5~WlѡG8ǏEO/ݺ+xtȟ$061(sZ{iv]W=AS8<Æߛ} DpNP#ij?0hO[Nf z3n\%7{{hsopOܞ?I`c4[_u)h z4hu]s*دz]'Pr}zih^mu_oKK86hrn^o맥Ch#lù;ù 9rny hER8tC[!G[H' е8CX46ExYAt7Bn~}'A xP0:;y@hH"G"I?[#%-5w~֜"! AI7"У5έ9oEJH`S=K{m ˾k9\ѸYs砛oAwHc(n ns $-dqQ/;4ҝ͈" LqL%C?NS6YՓ8 LS;ƶ糹ijUi%u$0$!o^zqSE>_v1JM&&ԓ zct\Eֽ;PZyUc|qS؍>H`'ؠwFϷ hǵN<|<]w '^oJ &AO3ZFE tGP4<iL>E p|ı4.$*80(XؠY fXs t tsHH8X$@$0QlM " 6h LDðHH 5@$@%=0, `f D AO41 HؠY$@$0QlM " 6h LDðHH 5@$@%=0, `f D AO41 HؠY$@$0QlM " 6h LDðHH 5@$@%=0, *c] IENDB`passage-4+dfsg1.orig/gamma256/gameSource/iPhone/arrows.png0000640000175000017500000000212511122273622022105 0ustar pabspabsPNG  IHDROqPLTE۶mmmIII$$$mI$mI$mmII$$mI$۶mmII$$mmII$$۶mmmIII$$ےmmIIm$$mmII$$mmII$$II$$$$۶۶mmImI$I$ےmmII$m$mmII$$mmII$$II$$$$ےmmIIm$$ImmII$$mmmII$$mmII$$II$$$$۶mmmIII$ےmImm$mI$mI$I$$۶۶mmImI$Iے۶mIm$mm۶I$mI۶$I$$ےmImm$IImI$mmmI$mI$I$$۶۶mmImI$I$ےmmII$m$ےmImm$II$mIm$Im$۶ےmmII$m$ImmII$$mmIm$Im$ImIm$I$mے۶mIm$mII$mےIm$Im$ےmmIIm$$ImmII$$mےmImImI*IDATH핱 0E!JetH +)X!5"  36!eQw3W=pĦ8,4qR'=,L^oZy%1%sir( '~NWn:}gyWrY5Vo-K/S @۫a[9dP(^ ov=u!ո=&ҿmy<ߖd;꽭a~}wM~50x|Oy߿v>{ppo)|2,c{X .<<IENDB`passage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/0000750000175000017500000000000011376537567021605 5ustar pabspabs././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090113_20090114175300581.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090113_2009011417530050000640000175000017500000000351511133423323026536 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 1 7 .7 01/13/2009 01/13/2009 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 2 .36 01/13/2009 01/13/2009 GBP GB GBP 300702040 .59 APPLE US 1001 Jason Rohrer Passage 1 2 .76 01/13/2009 01/13/2009 AUD AU AUD 300702040 1.19 APPLE US 1001 Jason Rohrer Passage 7 12 0 01/13/2009 01/13/2009 USD US USD 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/13/2009 01/13/2009 EUR FR EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/13/2009 01/13/2009 EUR IE EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/13/2009 01/13/2009 AUD AU AUD 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 1 .7 01/13/2009 01/13/2009 USD SG USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 3 .48 01/13/2009 01/13/2009 EUR DE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/13/2009 01/13/2009 SEK SE EUR 300702040 7 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/13/2009 01/13/2009 NOK NO EUR 300702040 6 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/13/2009 01/13/2009 SEK SE EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 2 81 01/13/2009 01/13/2009 JPY JP JPY 300702040 115 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/13/2009 01/13/2009 EUR ES EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 7 2 0 01/13/2009 01/13/2009 GBP GB GBP 300702040 0 ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090104_20090106150910384.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090104_2009010615091030000640000175000017500000000734111130672233026541 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 7 16 0 01/04/2009 01/04/2009 AUD AU AUD 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 2 0 01/04/2009 01/04/2009 NZD NZ AUD 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 1 81 01/04/2009 01/04/2009 JPY JP JPY 300702040 115 APPLE US 1001 Jason Rohrer Passage 7 11 0 01/04/2009 01/04/2009 EUR NL EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/04/2009 01/04/2009 USD IN USD 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 3 0 01/04/2009 01/04/2009 EUR PL EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/04/2009 01/04/2009 EUR LU EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/04/2009 01/04/2009 EUR ES EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 3 .7 01/04/2009 01/04/2009 CAD CA CAD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 7 2 0 01/04/2009 01/04/2009 CHF CH EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 4 0 01/04/2009 01/04/2009 USD SG USD 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 37 .7 01/04/2009 01/04/2009 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 7 19 0 01/04/2009 01/04/2009 EUR DE EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 4 .48 01/04/2009 01/04/2009 EUR DE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/04/2009 01/04/2009 EUR BE EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/04/2009 01/04/2009 EUR GR EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/04/2009 01/04/2009 EUR IE EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/04/2009 01/04/2009 EUR PT EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 19 0 01/04/2009 01/04/2009 CAD CA CAD 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 11 0 01/04/2009 01/04/2009 SEK SE EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/04/2009 01/04/2009 NOK NO EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 10 0 01/04/2009 01/04/2009 EUR FR EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 68 0 01/04/2009 01/04/2009 GBP GB GBP 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/04/2009 01/04/2009 EUR FI EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/04/2009 01/04/2009 EUR IT EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/04/2009 01/04/2009 DKK DK EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/04/2009 01/04/2009 USD AR USD 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 4 .36 01/04/2009 01/04/2009 GBP GB GBP 300702040 .59 APPLE US 1001 Jason Rohrer Passage 7 3 0 01/04/2009 01/04/2009 EUR FI EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/04/2009 01/04/2009 MXN MX USD 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 214 0 01/04/2009 01/04/2009 USD US USD 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/04/2009 01/04/2009 SEK SE EUR 300702040 7 APPLE US 1001 Jason Rohrer Passage 7 6 0 01/04/2009 01/04/2009 JPY JP JPY 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/04/2009 01/04/2009 USD PH USD 300702040 0 ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20081226_2008122915502587.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20081226_2008122915502580000640000175000017500000000441511126215207026561 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 1 -1 .7 12/26/2008 12/26/2008 USD US USD 300702040 -.99 APPLE US 1001 Jason Rohrer Passage 1 2 .7 12/26/2008 12/26/2008 USD SG USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 1 .7 12/26/2008 12/26/2008 USD AR USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 2 .48 12/26/2008 12/26/2008 EUR FR EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 2 .48 12/26/2008 12/26/2008 EUR AT EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 3 .48 12/26/2008 12/26/2008 DKK DK EUR 300702040 6 APPLE US 1001 Jason Rohrer Passage 1 31 .36 12/26/2008 12/26/2008 GBP GB GBP 300702040 .59 APPLE US 1001 Jason Rohrer Passage 1 25 .7 12/26/2008 12/26/2008 CAD CA CAD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/26/2008 12/26/2008 NOK NO EUR 300702040 6 APPLE US 1001 Jason Rohrer Passage 1 2 .48 12/26/2008 12/26/2008 EUR NL EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 254 .7 12/26/2008 12/26/2008 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 9 .48 12/26/2008 12/26/2008 EUR DE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 6 .76 12/26/2008 12/26/2008 AUD AU AUD 300702040 1.19 APPLE US 1001 Jason Rohrer Passage 1 1 81 12/26/2008 12/26/2008 JPY JP JPY 300702040 115 APPLE US 1001 Jason Rohrer Passage 1 2 .48 12/26/2008 12/26/2008 EUR PL EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 2 .48 12/26/2008 12/26/2008 EUR BE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/26/2008 12/26/2008 EUR IT EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 5 .48 12/26/2008 12/26/2008 SEK SE EUR 300702040 7 APPLE US 1001 Jason Rohrer Passage 1 2 .48 12/26/2008 12/26/2008 CHF CH EUR 300702040 1.1 ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090105_20090106150917837.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090105_2009010615091780000640000175000017500000000551311130672233026555 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 1 22 .7 01/05/2009 01/05/2009 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/05/2009 01/05/2009 CHF CH EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 2 .76 01/05/2009 01/05/2009 AUD AU AUD 300702040 1.19 APPLE US 1001 Jason Rohrer Passage 7 106 0 01/05/2009 01/05/2009 USD US USD 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/05/2009 01/05/2009 EUR DE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/05/2009 01/05/2009 EUR ES EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/05/2009 01/05/2009 DKK DK EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 2 81 01/05/2009 01/05/2009 JPY JP JPY 300702040 115 APPLE US 1001 Jason Rohrer Passage 7 22 0 01/05/2009 01/05/2009 GBP GB GBP 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/05/2009 01/05/2009 EUR IE EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/05/2009 01/05/2009 EUR IT EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 2 0 01/05/2009 01/05/2009 EUR NL EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 11 0 01/05/2009 01/05/2009 EUR DE EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 6 .36 01/05/2009 01/05/2009 GBP GB GBP 300702040 .59 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/05/2009 01/05/2009 EUR NL EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 7 6 0 01/05/2009 01/05/2009 SEK SE EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 9 0 01/05/2009 01/05/2009 AUD AU AUD 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 2 0 01/05/2009 01/05/2009 NZD NZ AUD 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 3 0 01/05/2009 01/05/2009 EUR FR EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/05/2009 01/05/2009 EUR FI EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/05/2009 01/05/2009 DKK DK EUR 300702040 6 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/05/2009 01/05/2009 EUR BE EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 6 0 01/05/2009 01/05/2009 CAD CA CAD 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 1 .7 01/05/2009 01/05/2009 CAD CA CAD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/05/2009 01/05/2009 USD SG USD 300702040 0 ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090108_20090114175235627.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090108_2009011417523560000640000175000017500000000364711133423323026560 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 7 32 0 01/08/2009 01/08/2009 USD US USD 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 3 0 01/08/2009 01/08/2009 CAD CA CAD 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/08/2009 01/08/2009 NZD NZ AUD 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/08/2009 01/08/2009 JPY JP JPY 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 1 .36 01/08/2009 01/08/2009 GBP GB GBP 300702040 .59 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/08/2009 01/08/2009 EUR AT EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 1 .7 01/08/2009 01/08/2009 USD HK USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 7 4 0 01/08/2009 01/08/2009 GBP GB GBP 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/08/2009 01/08/2009 EUR ES EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/08/2009 01/08/2009 EUR BE EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 2 81 01/08/2009 01/08/2009 JPY JP JPY 300702040 115 APPLE US 1001 Jason Rohrer Passage 1 26 .7 01/08/2009 01/08/2009 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/08/2009 01/08/2009 EUR FR EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 7 2 0 01/08/2009 01/08/2009 EUR FI EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 3 0 01/08/2009 01/08/2009 EUR DE EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/08/2009 01/08/2009 CHF CH EUR 300702040 0 ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090102_2009010615085482.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090102_2009010615085480000640000175000017500000000220011130672233026540 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 1 26 .7 01/02/2009 01/02/2009 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 2 .48 01/02/2009 01/02/2009 EUR DE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 81 01/02/2009 01/02/2009 JPY JP JPY 300702040 115 APPLE US 1001 Jason Rohrer Passage 1 8 .36 01/02/2009 01/02/2009 GBP GB GBP 300702040 .59 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/02/2009 01/02/2009 EUR NL EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 5 .7 01/02/2009 01/02/2009 CAD CA CAD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 3 .48 01/02/2009 01/02/2009 EUR FR EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/02/2009 01/02/2009 SEK SE EUR 300702040 7 ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090101_20090102170648169.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090101_2009010217064810000640000175000017500000000252611127444742026552 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 1 3 .76 01/01/2009 01/01/2009 AUD AU AUD 300702040 1.19 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/01/2009 01/01/2009 EUR LU EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 81 01/01/2009 01/01/2009 JPY JP JPY 300702040 115 APPLE US 1001 Jason Rohrer Passage 1 1 .7 01/01/2009 01/01/2009 CAD CA CAD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 1 .76 01/01/2009 01/01/2009 NZD NZ AUD 300702040 1.29 APPLE US 1001 Jason Rohrer Passage 1 33 .7 01/01/2009 01/01/2009 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 6 .36 01/01/2009 01/01/2009 GBP GB GBP 300702040 .59 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/01/2009 01/01/2009 EUR FR EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 4 .48 01/01/2009 01/01/2009 SEK SE EUR 300702040 7 APPLE US 1001 Jason Rohrer Passage 1 2 .48 01/01/2009 01/01/2009 EUR DE EUR 300702040 .79 ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20081230_2009010217055919.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20081230_2009010217055910000640000175000017500000000337411127444742026560 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 1 2 .48 12/30/2008 12/30/2008 NOK NO EUR 300702040 6 APPLE US 1001 Jason Rohrer Passage 1 3 .76 12/30/2008 12/30/2008 NZD NZ AUD 300702040 1.29 APPLE US 1001 Jason Rohrer Passage 1 2 .48 12/30/2008 12/30/2008 EUR FI EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .7 12/30/2008 12/30/2008 USD IN USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 2 .48 12/30/2008 12/30/2008 EUR FR EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 3 .48 12/30/2008 12/30/2008 EUR NL EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/30/2008 12/30/2008 EUR IT EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 2 .48 12/30/2008 12/30/2008 EUR DE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 54 .7 12/30/2008 12/30/2008 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 12 .36 12/30/2008 12/30/2008 GBP GB GBP 300702040 .59 APPLE US 1001 Jason Rohrer Passage 1 3 .48 12/30/2008 12/30/2008 SEK SE EUR 300702040 7 APPLE US 1001 Jason Rohrer Passage 1 4 .76 12/30/2008 12/30/2008 AUD AU AUD 300702040 1.19 APPLE US 1001 Jason Rohrer Passage 1 6 .7 12/30/2008 12/30/2008 CAD CA CAD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 2 .7 12/30/2008 12/30/2008 USD SG USD 300702040 .99 ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090111_20090114175250853.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090111_2009011417525080000640000175000017500000000320011133423323026532 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 7 2 0 01/11/2009 01/11/2009 GBP GB GBP 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/11/2009 01/11/2009 EUR FR EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/11/2009 01/11/2009 CAD CA CAD 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 1 .7 01/11/2009 01/11/2009 USD AR USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/11/2009 01/11/2009 EUR FI EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/11/2009 01/11/2009 AUD AU AUD 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 1 .76 01/11/2009 01/11/2009 AUD AU AUD 300702040 1.19 APPLE US 1001 Jason Rohrer Passage 7 24 0 01/11/2009 01/11/2009 USD US USD 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/11/2009 01/11/2009 SEK SE EUR 300702040 7 APPLE US 1001 Jason Rohrer Passage 1 29 .7 01/11/2009 01/11/2009 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/11/2009 01/11/2009 EUR DE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 2 81 01/11/2009 01/11/2009 JPY JP JPY 300702040 115 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/11/2009 01/11/2009 EUR FR EUR 300702040 .79 ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20081229_20090102170456173.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20081229_2009010217045610000640000175000017500000000322411127444742026556 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/29/2008 12/29/2008 EUR AT EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 6 .48 12/29/2008 12/29/2008 EUR DE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 3 .48 12/29/2008 12/29/2008 EUR FR EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 5 .7 12/29/2008 12/29/2008 CAD CA CAD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/29/2008 12/29/2008 CHF CH EUR 300702040 1.1 APPLE US 1001 Jason Rohrer Passage 1 90 .7 12/29/2008 12/29/2008 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 13 .36 12/29/2008 12/29/2008 GBP GB GBP 300702040 .59 APPLE US 1001 Jason Rohrer Passage 1 1 .7 12/29/2008 12/29/2008 USD SG USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 7 .48 12/29/2008 12/29/2008 EUR NL EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 7 .76 12/29/2008 12/29/2008 AUD AU AUD 300702040 1.19 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/29/2008 12/29/2008 EUR HU EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/29/2008 12/29/2008 EUR FI EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/29/2008 12/29/2008 SEK SE EUR 300702040 7 ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20081225_20081229155019662.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20081225_2008122915501960000640000175000017500000000355011126215207026560 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 1 99 .7 12/25/2008 12/25/2008 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 3 .48 12/25/2008 12/25/2008 EUR FR EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 5 .48 12/25/2008 12/25/2008 EUR DE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/25/2008 12/25/2008 EUR PT EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/25/2008 12/25/2008 EUR IE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 4 .48 12/25/2008 12/25/2008 EUR NL EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/25/2008 12/25/2008 EUR ES EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 5 .48 12/25/2008 12/25/2008 SEK SE EUR 300702040 7 APPLE US 1001 Jason Rohrer Passage 1 4 .48 12/25/2008 12/25/2008 DKK DK EUR 300702040 6 APPLE US 1001 Jason Rohrer Passage 1 1 .76 12/25/2008 12/25/2008 NZD NZ AUD 300702040 1.29 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/25/2008 12/25/2008 EUR BE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 6 .7 12/25/2008 12/25/2008 CAD CA CAD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 8 .76 12/25/2008 12/25/2008 AUD AU AUD 300702040 1.19 APPLE US 1001 Jason Rohrer Passage 1 32 .36 12/25/2008 12/25/2008 GBP GB GBP 300702040 .59 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/25/2008 12/25/2008 EUR IT EUR 300702040 .79 ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20081223_20081229154951691.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20081223_2008122915495160000640000175000017500000000100611126215207026554 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 1 1 .7 12/23/2008 12/23/2008 CAD CA CAD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 3 .7 12/23/2008 12/23/2008 USD US USD 300702040 .99 ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20081228_20081229155036881.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20081228_2008122915503680000640000175000017500000000407411126215207026566 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 1 14 .36 12/28/2008 12/28/2008 GBP GB GBP 300702040 .59 APPLE US 1001 Jason Rohrer Passage 1 7 .7 12/28/2008 12/28/2008 CAD CA CAD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 79 .7 12/28/2008 12/28/2008 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 2 .48 12/28/2008 12/28/2008 EUR FI EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/28/2008 12/28/2008 EUR ES EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 2 .48 12/28/2008 12/28/2008 CHF CH EUR 300702040 1.1 APPLE US 1001 Jason Rohrer Passage 1 5 .76 12/28/2008 12/28/2008 AUD AU AUD 300702040 1.19 APPLE US 1001 Jason Rohrer Passage 1 1 .76 12/28/2008 12/28/2008 NZD NZ AUD 300702040 1.29 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/28/2008 12/28/2008 EUR IE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 81 12/28/2008 12/28/2008 JPY JP JPY 300702040 115 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/28/2008 12/28/2008 EUR PL EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 2 .48 12/28/2008 12/28/2008 EUR FR EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/28/2008 12/28/2008 EUR IT EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 3 .48 12/28/2008 12/28/2008 SEK SE EUR 300702040 7 APPLE US 1001 Jason Rohrer Passage 1 8 .48 12/28/2008 12/28/2008 EUR DE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .7 12/28/2008 12/28/2008 USD SG USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 3 .48 12/28/2008 12/28/2008 EUR NL EUR 300702040 .79 ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090107_20090114175227209.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090107_2009011417522720000640000175000017500000000420411133423323026542 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/07/2009 01/07/2009 SEK SE EUR 300702040 7 APPLE US 1001 Jason Rohrer Passage 7 2 0 01/07/2009 01/07/2009 AUD AU AUD 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 42 0 01/07/2009 01/07/2009 USD US USD 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 4 0 01/07/2009 01/07/2009 EUR DE EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/07/2009 01/07/2009 EUR ES EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 3 .48 01/07/2009 01/07/2009 EUR DE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .7 01/07/2009 01/07/2009 CAD CA CAD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 2 .76 01/07/2009 01/07/2009 AUD AU AUD 300702040 1.19 APPLE US 1001 Jason Rohrer Passage 1 3 .48 01/07/2009 01/07/2009 EUR FR EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/07/2009 01/07/2009 EUR IT EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 3 0 01/07/2009 01/07/2009 CAD CA CAD 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 3 0 01/07/2009 01/07/2009 SEK SE EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 2 0 01/07/2009 01/07/2009 DKK DK EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 25 .7 01/07/2009 01/07/2009 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 7 2 0 01/07/2009 01/07/2009 EUR FR EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 10 0 01/07/2009 01/07/2009 GBP GB GBP 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 2 .36 01/07/2009 01/07/2009 GBP GB GBP 300702040 .59 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/07/2009 01/07/2009 EUR NL EUR 300702040 .79 ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090103_20090106150905023.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090103_2009010615090500000640000175000017500000000252211130672233026535 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 1 29 .7 01/03/2009 01/03/2009 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/03/2009 01/03/2009 EUR IE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 7 15 0 01/03/2009 01/03/2009 CAD CA CAD 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 2 81 01/03/2009 01/03/2009 JPY JP JPY 300702040 115 APPLE US 1001 Jason Rohrer Passage 7 183 0 01/03/2009 01/03/2009 USD US USD 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 1 .76 01/03/2009 01/03/2009 AUD AU AUD 300702040 1.19 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/03/2009 01/03/2009 EUR ES EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/03/2009 01/03/2009 EUR FR EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 2 .7 01/03/2009 01/03/2009 CAD CA CAD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 6 .36 01/03/2009 01/03/2009 GBP GB GBP 300702040 .59 ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090109_20090114175240828.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090109_2009011417524080000640000175000017500000000365511133423323026556 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 1 16 .7 01/09/2009 01/09/2009 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 7 23 0 01/09/2009 01/09/2009 USD US USD 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 2 .48 01/09/2009 01/09/2009 EUR FR EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 7 3 0 01/09/2009 01/09/2009 CAD CA CAD 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 1 81 01/09/2009 01/09/2009 JPY JP JPY 300702040 115 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/09/2009 01/09/2009 EUR HU EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 2 0 01/09/2009 01/09/2009 GBP GB GBP 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 2 .36 01/09/2009 01/09/2009 GBP GB GBP 300702040 .59 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/09/2009 01/09/2009 SEK SE EUR 300702040 7 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/09/2009 01/09/2009 JPY JP JPY 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/09/2009 01/09/2009 EUR IE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/09/2009 01/09/2009 EUR IT EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 2 .7 01/09/2009 01/09/2009 CAD CA CAD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/09/2009 01/09/2009 EUR CZ EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/09/2009 01/09/2009 EUR FR EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 2 0 01/09/2009 01/09/2009 DKK DK EUR 300702040 0 ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20081224_20081229155013664.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20081224_2008122915501360000640000175000017500000000322211126215207026545 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 1 8 .36 12/24/2008 12/24/2008 GBP GB GBP 300702040 .59 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/24/2008 12/24/2008 EUR BE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 81 12/24/2008 12/24/2008 JPY JP JPY 300702040 115 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/24/2008 12/24/2008 EUR DE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/24/2008 12/24/2008 SEK SE EUR 300702040 7 APPLE US 1001 Jason Rohrer Passage 1 162 .7 12/24/2008 12/24/2008 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 2 .48 12/24/2008 12/24/2008 EUR FI EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/24/2008 12/24/2008 EUR ES EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 2 .48 12/24/2008 12/24/2008 EUR FR EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/24/2008 12/24/2008 EUR NL EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 0 12/24/2008 12/24/2008 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/24/2008 12/24/2008 EUR IE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 11 .7 12/24/2008 12/24/2008 CAD CA CAD 300702040 .99 ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20081227_20081229155031472.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20081227_2008122915503140000640000175000017500000000526611126215207026560 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/27/2008 12/27/2008 EUR GR EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 2 .48 12/27/2008 12/27/2008 EUR NL EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 7 .48 12/27/2008 12/27/2008 SEK SE EUR 300702040 7 APPLE US 1001 Jason Rohrer Passage 1 5 .48 12/27/2008 12/27/2008 EUR FR EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 43 .36 12/27/2008 12/27/2008 GBP GB GBP 300702040 .59 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/27/2008 12/27/2008 EUR BE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/27/2008 12/27/2008 CHF CH EUR 300702040 1.1 APPLE US 1001 Jason Rohrer Passage 1 1 .7 12/27/2008 12/27/2008 MXN MX USD 300702040 10 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/27/2008 12/27/2008 EUR PL EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 141 .7 12/27/2008 12/27/2008 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 14 .48 12/27/2008 12/27/2008 EUR DE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .7 12/27/2008 12/27/2008 USD SG USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/27/2008 12/27/2008 EUR ES EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .7 12/27/2008 12/27/2008 USD PH USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 3 .76 12/27/2008 12/27/2008 NZD NZ AUD 300702040 1.29 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/27/2008 12/27/2008 EUR CZ EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 2 .48 12/27/2008 12/27/2008 EUR AT EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/27/2008 12/27/2008 EUR IE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 3 .7 12/27/2008 12/27/2008 CAD CA CAD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 2 .48 12/27/2008 12/27/2008 DKK DK EUR 300702040 6 APPLE US 1001 Jason Rohrer Passage 1 15 .76 12/27/2008 12/27/2008 AUD AU AUD 300702040 1.19 APPLE US 1001 Jason Rohrer Passage 1 3 81 12/27/2008 12/27/2008 JPY JP JPY 300702040 115 APPLE US 1001 Jason Rohrer Passage 1 2 .48 12/27/2008 12/27/2008 EUR FI EUR 300702040 .79 ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20081231_2009010217062259.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20081231_2009010217062250000640000175000017500000000220111127444742026540 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 1 4 .7 12/31/2008 12/31/2008 CAD CA CAD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/31/2008 12/31/2008 EUR DE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/31/2008 12/31/2008 EUR FI EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 81 12/31/2008 12/31/2008 JPY JP JPY 300702040 115 APPLE US 1001 Jason Rohrer Passage 1 32 .7 12/31/2008 12/31/2008 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/31/2008 12/31/2008 EUR IE EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 1 .48 12/31/2008 12/31/2008 SEK SE EUR 300702040 7 APPLE US 1001 Jason Rohrer Passage 1 10 .36 12/31/2008 12/31/2008 GBP GB GBP 300702040 .59 ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090110_20090114175246221.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090110_2009011417524620000640000175000017500000000333711133423323026543 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 7 17 0 01/10/2009 01/10/2009 USD US USD 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 1 .7 01/10/2009 01/10/2009 USD SG USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 1 .36 01/10/2009 01/10/2009 GBP GB GBP 300702040 .59 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/10/2009 01/10/2009 CHF CH EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/10/2009 01/10/2009 EUR DE EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/10/2009 01/10/2009 EUR NL EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/10/2009 01/10/2009 EUR FI EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 1 .7 01/10/2009 01/10/2009 CAD CA CAD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 1 81 01/10/2009 01/10/2009 JPY JP JPY 300702040 115 APPLE US 1001 Jason Rohrer Passage 1 16 .7 01/10/2009 01/10/2009 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 7 2 0 01/10/2009 01/10/2009 AUD AU AUD 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 2 .76 01/10/2009 01/10/2009 AUD AU AUD 300702040 1.19 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/10/2009 01/10/2009 GBP GB GBP 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 2 0 01/10/2009 01/10/2009 CAD CA CAD 300702040 0 ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090112_200901141752552.txtpassage-4+dfsg1.orig/gamma256/gameSource/iPhone/reports/S_D_80075145_999998_20090112_2009011417525520000640000175000017500000000265511133423323026547 0ustar pabspabsProvider Provider Country Vendor Identifier UPC ISRC Artist / Show Title / Episode / Season Label/Studio/Network Product Type Identifier Units Royalty Price Begin Date End Date Customer Currency Country Code Royalty Currency Preorder Season Pass ISAN Apple Identifier Customer Price CMA Asset/Content Flavor APPLE US 1001 Jason Rohrer Passage 1 3 .36 01/12/2009 01/12/2009 GBP GB GBP 300702040 .59 APPLE US 1001 Jason Rohrer Passage 7 2 0 01/12/2009 01/12/2009 AUD AU AUD 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 1 .7 01/12/2009 01/12/2009 USD SG USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/12/2009 01/12/2009 EUR SK EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 7 10 0 01/12/2009 01/12/2009 USD US USD 300702040 0 APPLE US 1001 Jason Rohrer Passage 1 20 .7 01/12/2009 01/12/2009 USD US USD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 1 1 .48 01/12/2009 01/12/2009 EUR PT EUR 300702040 .79 APPLE US 1001 Jason Rohrer Passage 1 2 .7 01/12/2009 01/12/2009 CAD CA CAD 300702040 .99 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/12/2009 01/12/2009 EUR AT EUR 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 3 0 01/12/2009 01/12/2009 GBP GB GBP 300702040 0 APPLE US 1001 Jason Rohrer Passage 7 1 0 01/12/2009 01/12/2009 SEK SE EUR 300702040 0 passage-4+dfsg1.orig/gamma256/gameSource/iPhone/drawIntoScreen.h0000640000175000017500000000102711122342077023163 0ustar pabspabs// interface for generic screen drawing framework #include typedef uint32_t Uint32; void initScreenDrawer( Uint32 *inScreenBuffer, int inWidth, int inHeight ); // each pixel is 4 characters void drawIntoScreen( Uint32 *inScreenBuffer, int inWidth, int inHeight ); // set device orientation from accelerometer void setOrientation( float inX, float inY ); void touchStartPoint( float inX, float inY ); void touchMovePoint( float inX, float inY ); void touchEndPoint( float inX, float inY ); void freeScreenDrawer(); passage-4+dfsg1.orig/gamma256/gameSource/iPhone/blowUp.h0000640000175000017500000000050511121760321021477 0ustar pabspabs#include "drawIntoScreen.h" /** * Blows an image up onto the screen using nearest neighbor (pixelated) * interpolation. */ void blowupOntoScreen( Uint32 *inImage, int inWidth, int inHeight, int inBlowFactor, Uint32 *inScreenPixels, int inScreenWidth, int inScreenHeight ); passage-4+dfsg1.orig/gamma256/gameSource/iPhone/gameWindowApp_Prefix.pch0000640000175000017500000000030311121526563024635 0ustar pabspabs// // Prefix header for all source files of the 'testWindowApp' target in the 'testWindowApp' project // #ifdef __OBJC__ #import #import #endif passage-4+dfsg1.orig/gamma256/gameSource/iPhone/LargeIcon.png0000640000175000017500000000410211122776043022435 0ustar pabspabsPNG  IHDR{C IDATxݱoUqHP{iSL]P] 8[JsTj/{ZwwITMX8t&rvZZZ5]dڤ/v2      @ɪ"5#kbN-oGfv\ϡ5      ~wqa 6ry[;J̎OCI]oN@@@@@@s^\:Y ms2;S?xj~s(     va}&ݕ\.nfWm<&;ݻN      Yva=:t[>6p]D>@@@@@@ҷkjzƗuK}4qIhy!+mb @@@@@@ /V??2rg^5}sf1YmBihGG9J@@@@@@J 2ݵm8k\6]0px8Z4<4rdWz>ggs{&7'B      @ɪ ܢ_1m@@@@@@ҷܪm4IENDB`passage-4+dfsg1.orig/gamma256/gameSource/iPhone/gameWindowApp.xcodeproj/0000750000175000017500000000000011376537567024645 5ustar pabspabspassage-4+dfsg1.orig/gamma256/gameSource/iPhone/gameWindowApp.xcodeproj/jasonrohrer.pbxuser0000640000175000017500000011405311124755664030607 0ustar pabspabs// !$*UTF8*$! { 1D6058900D05DD3D006BFB54 /* Passage */ = { activeExec = 0; executables = ( DA86AE6F0EF538E500054E6B /* Passage */, ); }; 29B97313FDCFA39411CA2CEA /* Project object */ = { activeBuildConfigurationName = Distribution; activeExecutable = DA86AE6F0EF538E500054E6B /* Passage */; activeSDKPreference = iphoneos2.2; activeTarget = 1D6058900D05DD3D006BFB54 /* Passage */; addToTargets = ( 1D6058900D05DD3D006BFB54 /* Passage */, ); breakpoints = ( ); codeSenseManager = DA86AE940EF5391600054E6B /* Code sense */; executables = ( DA86AE6F0EF538E500054E6B /* Passage */, ); perUserDictionary = { PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; PBXFileTableDataSourceColumnWidthsKey = ( 22, 300, 262.58349609375, ); PBXFileTableDataSourceColumnsKey = ( PBXExecutablesDataSource_ActiveFlagID, PBXExecutablesDataSource_NameID, PBXExecutablesDataSource_CommentsID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 375, 20, 48, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXConfiguration.PBXFileTableDataSource3.PBXSymbolsDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXSymbolsDataSource_SymbolNameID; PBXFileTableDataSourceColumnWidthsKey = ( 16, 200, 50, 315, ); PBXFileTableDataSourceColumnsKey = ( PBXSymbolsDataSource_SymbolTypeIconID, PBXSymbolsDataSource_SymbolNameID, PBXSymbolsDataSource_SymbolTypeID, PBXSymbolsDataSource_ReferenceNameID, ); }; PBXConfiguration.PBXFileTableDataSource3.XCSCMDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 20, 351, 20, 48.16259765625, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_SCM_ColumnID, PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 335, 60, 20, 48, 43, 43, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXTargetDataSource_PrimaryAttribute, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, ); }; PBXPerProjectTemplateStateSaveDate = 251925228; PBXWorkspaceStateSaveDate = 251925228; }; perUserProjectItems = { DA0EC5C40F03E66500DC5B33 /* PBXTextBookmark */ = DA0EC5C40F03E66500DC5B33 /* PBXTextBookmark */; DA0EC60E0F03FE7400DC5B33 /* PBXTextBookmark */ = DA0EC60E0F03FE7400DC5B33 /* PBXTextBookmark */; DA0EC6190F04026C00DC5B33 /* PBXTextBookmark */ = DA0EC6190F04026C00DC5B33 /* PBXTextBookmark */; DA0EC64F0F0412E300DC5B33 /* PBXTextBookmark */ = DA0EC64F0F0412E300DC5B33 /* PBXTextBookmark */; DA0EC6500F0412E300DC5B33 /* PlistBookmark */ = DA0EC6500F0412E300DC5B33 /* PlistBookmark */; DA0EC65F0F0412F800DC5B33 /* PBXTextBookmark */ = DA0EC65F0F0412F800DC5B33 /* PBXTextBookmark */; DA0EC6600F0412F800DC5B33 /* PBXTextBookmark */ = DA0EC6600F0412F800DC5B33 /* PBXTextBookmark */; DA0EC6610F0412F800DC5B33 /* PlistBookmark */ = DA0EC6610F0412F800DC5B33 /* PlistBookmark */; DA12F3600EF6EB5E00A40C6D /* PBXTextBookmark */ = DA12F3600EF6EB5E00A40C6D /* PBXTextBookmark */; DA12F3620EF6EB5E00A40C6D /* PBXTextBookmark */ = DA12F3620EF6EB5E00A40C6D /* PBXTextBookmark */; DA12F3640EF6EB5E00A40C6D /* PBXTextBookmark */ = DA12F3640EF6EB5E00A40C6D /* PBXTextBookmark */; DA12F3660EF6EB5E00A40C6D /* PBXTextBookmark */ = DA12F3660EF6EB5E00A40C6D /* PBXTextBookmark */; DA12F3680EF6EB5E00A40C6D /* PBXTextBookmark */ = DA12F3680EF6EB5E00A40C6D /* PBXTextBookmark */; DA12F36D0EF6EB5E00A40C6D /* PBXTextBookmark */ = DA12F36D0EF6EB5E00A40C6D /* PBXTextBookmark */; DA12F36F0EF6EB5E00A40C6D /* PBXTextBookmark */ = DA12F36F0EF6EB5E00A40C6D /* PBXTextBookmark */; DA12F3710EF6EB5E00A40C6D /* PBXTextBookmark */ = DA12F3710EF6EB5E00A40C6D /* PBXTextBookmark */; DA12F3730EF6EB5E00A40C6D /* PBXTextBookmark */ = DA12F3730EF6EB5E00A40C6D /* PBXTextBookmark */; DA12F3750EF6EB5E00A40C6D /* PBXTextBookmark */ = DA12F3750EF6EB5E00A40C6D /* PBXTextBookmark */; DA12F3770EF6EB5E00A40C6D /* PBXTextBookmark */ = DA12F3770EF6EB5E00A40C6D /* PBXTextBookmark */; DA12F3790EF6EB5E00A40C6D /* PBXTextBookmark */ = DA12F3790EF6EB5E00A40C6D /* PBXTextBookmark */; DA12F37B0EF6EB5E00A40C6D /* PBXTextBookmark */ = DA12F37B0EF6EB5E00A40C6D /* PBXTextBookmark */; DA12F37D0EF6EB5E00A40C6D /* PBXTextBookmark */ = DA12F37D0EF6EB5E00A40C6D /* PBXTextBookmark */; DA12F37F0EF6EB5E00A40C6D /* PBXTextBookmark */ = DA12F37F0EF6EB5E00A40C6D /* PBXTextBookmark */; DA12F3810EF6EB5E00A40C6D /* PBXTextBookmark */ = DA12F3810EF6EB5E00A40C6D /* PBXTextBookmark */; DA12F38A0EF6EB9F00A40C6D /* PBXTextBookmark */ = DA12F38A0EF6EB9F00A40C6D /* PBXTextBookmark */; DA12F3A80EF6EDCA00A40C6D /* PBXTextBookmark */ = DA12F3A80EF6EDCA00A40C6D /* PBXTextBookmark */; DA12F3A90EF6EDCA00A40C6D /* PBXTextBookmark */ = DA12F3A90EF6EDCA00A40C6D /* PBXTextBookmark */; DA12F3B30EF6EDCA00A40C6D /* PBXTextBookmark */ = DA12F3B30EF6EDCA00A40C6D /* PBXTextBookmark */; DA12F3CC0EF6EEC700A40C6D /* PBXTextBookmark */ = DA12F3CC0EF6EEC700A40C6D /* PBXTextBookmark */; DA12F3CD0EF6EEC700A40C6D /* PBXTextBookmark */ = DA12F3CD0EF6EEC700A40C6D /* PBXTextBookmark */; DA12F3D90EF6EFFB00A40C6D /* PBXTextBookmark */ = DA12F3D90EF6EFFB00A40C6D /* PBXTextBookmark */; DA12F3DC0EF6EFFB00A40C6D /* PBXTextBookmark */ = DA12F3DC0EF6EFFB00A40C6D /* PBXTextBookmark */; DA12F3F10EF6F1A100A40C6D /* PBXTextBookmark */ = DA12F3F10EF6F1A100A40C6D /* PBXTextBookmark */; DA7F10FB0EF6CCF600CB6D50 /* PBXTextBookmark */ = DA7F10FB0EF6CCF600CB6D50 /* PBXTextBookmark */; DA7F11AD0EF6D9CB00CB6D50 /* PBXTextBookmark */ = DA7F11AD0EF6D9CB00CB6D50 /* PBXTextBookmark */; DA7F11AE0EF6D9CB00CB6D50 /* PBXTextBookmark */ = DA7F11AE0EF6D9CB00CB6D50 /* PBXTextBookmark */; DA7F11B10EF6D9CB00CB6D50 /* PBXTextBookmark */ = DA7F11B10EF6D9CB00CB6D50 /* PBXTextBookmark */; DA7F12040EF6E3A400CB6D50 /* PBXTextBookmark */ = DA7F12040EF6E3A400CB6D50 /* PBXTextBookmark */; DA8277520EF9FC240061079D /* PBXTextBookmark */ = DA8277520EF9FC240061079D /* PBXTextBookmark */; DA82779E0EFA03960061079D /* PBXTextBookmark */ = DA82779E0EFA03960061079D /* PBXTextBookmark */; DA86AEB60EF53C5800054E6B /* PBXTextBookmark */ = DA86AEB60EF53C5800054E6B /* PBXTextBookmark */; DA86AEE50EF53F3C00054E6B /* PlistBookmark */ = DA86AEE50EF53F3C00054E6B /* PlistBookmark */; DA8C9E300EF809CA002FCA67 /* PBXTextBookmark */ = DA8C9E300EF809CA002FCA67 /* PBXTextBookmark */; DA8C9E310EF809CA002FCA67 /* PBXTextBookmark */ = DA8C9E310EF809CA002FCA67 /* PBXTextBookmark */; DA8C9E320EF809CA002FCA67 /* PBXTextBookmark */ = DA8C9E320EF809CA002FCA67 /* PBXTextBookmark */; DA8C9E560EF80B73002FCA67 /* PBXTextBookmark */ = DA8C9E560EF80B73002FCA67 /* PBXTextBookmark */; DA8C9E710EF80DA9002FCA67 /* PBXTextBookmark */ = DA8C9E710EF80DA9002FCA67 /* PBXTextBookmark */; DA8C9E730EF80DA9002FCA67 /* PBXTextBookmark */ = DA8C9E730EF80DA9002FCA67 /* PBXTextBookmark */; DA8C9EAC0EF811E6002FCA67 /* PBXTextBookmark */ = DA8C9EAC0EF811E6002FCA67 /* PBXTextBookmark */; DA8C9EAE0EF811E6002FCA67 /* PBXTextBookmark */ = DA8C9EAE0EF811E6002FCA67 /* PBXTextBookmark */; DA8C9F4E0EF8266C002FCA67 /* PBXTextBookmark */ = DA8C9F4E0EF8266C002FCA67 /* PBXTextBookmark */; DA8C9F4F0EF8266C002FCA67 /* PBXTextBookmark */ = DA8C9F4F0EF8266C002FCA67 /* PBXTextBookmark */; DA8C9F500EF8266C002FCA67 /* PBXTextBookmark */ = DA8C9F500EF8266C002FCA67 /* PBXTextBookmark */; DA90DDCD0EFAF5A3001BABB5 /* PBXTextBookmark */ = DA90DDCD0EFAF5A3001BABB5 /* PBXTextBookmark */; DA90DDCE0EFAF5A3001BABB5 /* PBXTextBookmark */ = DA90DDCE0EFAF5A3001BABB5 /* PBXTextBookmark */; DA90DDD10EFAF5A3001BABB5 /* PBXTextBookmark */ = DA90DDD10EFAF5A3001BABB5 /* PBXTextBookmark */; DA90DDD20EFAF5A3001BABB5 /* PBXTextBookmark */ = DA90DDD20EFAF5A3001BABB5 /* PBXTextBookmark */; DA90DDD50EFAF5A3001BABB5 /* PBXTextBookmark */ = DA90DDD50EFAF5A3001BABB5 /* PBXTextBookmark */; DA90DDD70EFAF5A3001BABB5 /* PBXTextBookmark */ = DA90DDD70EFAF5A3001BABB5 /* PBXTextBookmark */; DA90DDDD0EFAF5A3001BABB5 /* PBXTextBookmark */ = DA90DDDD0EFAF5A3001BABB5 /* PBXTextBookmark */; DA90DDE00EFAF5A3001BABB5 /* PBXTextBookmark */ = DA90DDE00EFAF5A3001BABB5 /* PBXTextBookmark */; DA90DDE10EFAF5A3001BABB5 /* PBXTextBookmark */ = DA90DDE10EFAF5A3001BABB5 /* PBXTextBookmark */; DA90DDE90EFAF5A3001BABB5 /* PBXTextBookmark */ = DA90DDE90EFAF5A3001BABB5 /* PBXTextBookmark */; DA90DDEF0EFAF5A3001BABB5 /* PBXTextBookmark */ = DA90DDEF0EFAF5A3001BABB5 /* PBXTextBookmark */; DA90DDF30EFAF5A3001BABB5 /* PBXTextBookmark */ = DA90DDF30EFAF5A3001BABB5 /* PBXTextBookmark */; DA9E30CD0EFC240B00DFACC7 /* PBXTextBookmark */ = DA9E30CD0EFC240B00DFACC7 /* PBXTextBookmark */; DA9E30CF0EFC240B00DFACC7 /* PBXTextBookmark */ = DA9E30CF0EFC240B00DFACC7 /* PBXTextBookmark */; DA9E30D00EFC240B00DFACC7 /* PBXTextBookmark */ = DA9E30D00EFC240B00DFACC7 /* PBXTextBookmark */; DAADB67F0EF981DA00169CE3 /* PBXTextBookmark */ = DAADB67F0EF981DA00169CE3 /* PBXTextBookmark */; DAADB6880EF981DA00169CE3 /* PBXTextBookmark */ = DAADB6880EF981DA00169CE3 /* PBXTextBookmark */; }; sourceControlManager = DA86AE930EF5391600054E6B /* Source Control */; userBuildSettings = { }; }; 29B97316FDCFA39411CA2CEA /* main.m */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {553, 574}}"; sepNavSelRange = "{447, 0}"; sepNavVisRange = "{252, 661}"; sepNavWindowFrame = "{{172, 138}, {750, 558}}"; }; }; 8D1107310486CEB800E47090 /* Info.plist */ = { uiCtxt = { sepNavWindowFrame = "{{61, 141}, {750, 558}}"; }; }; DA0EC5C40F03E66500DC5B33 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3CF0EF6EED000A40C6D /* common.h */; name = "common.h: 6"; rLen = 38; rLoc = 51; rType = 0; vrLen = 252; vrLoc = 0; }; DA0EC60E0F03FE7400DC5B33 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3400EF6E8BD00A40C6D /* common.cpp */; name = "common.cpp: 24"; rLen = 0; rLoc = 498; rType = 0; vrLen = 460; vrLoc = 83; }; DA0EC6190F04026C00DC5B33 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3410EF6E8BD00A40C6D /* game.cpp */; name = "game.cpp: 420"; rLen = 0; rLoc = 9572; rType = 0; vrLen = 656; vrLoc = 8975; }; DA0EC64F0F0412E300DC5B33 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3780EF6EB5E00A40C6D /* map.cpp */; name = "map.cpp: 243"; rLen = 0; rLoc = 6332; rType = 0; vrLen = 330; vrLoc = 0; }; DA0EC6500F0412E300DC5B33 /* PlistBookmark */ = { isa = PlistBookmark; fRef = 8D1107310486CEB800E47090 /* Info.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( ); name = /Users/jasonrohrer/cpp/gamma256/gameSource/iPhone/Info.plist; rLen = 0; rLoc = 2147483647; }; DA0EC65F0F0412F800DC5B33 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA90DD110EFAC2AF001BABB5 /* Timbre.cpp */; name = "Timbre.cpp: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 362; vrLoc = 0; }; DA0EC6600F0412F800DC5B33 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA90DD110EFAC2AF001BABB5 /* Timbre.cpp */; name = "Timbre.cpp: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 362; vrLoc = 0; }; DA0EC6610F0412F800DC5B33 /* PlistBookmark */ = { isa = PlistBookmark; fRef = 8D1107310486CEB800E47090 /* Info.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( ); name = /Users/jasonrohrer/cpp/gamma256/gameSource/iPhone/Info.plist; rLen = 0; rLoc = 2147483647; }; DA12F32D0EF6E89F00A40C6D /* World.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {787, 714}}"; sepNavSelRange = "{0, 44}"; sepNavVisRange = "{0, 755}"; }; }; DA12F32E0EF6E89F00A40C6D /* World.cpp */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {553, 13482}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 312}"; }; }; DA12F3320EF6E89F00A40C6D /* map.cpp */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {553, 3948}}"; sepNavSelRange = "{6332, 0}"; sepNavVisRange = "{0, 330}"; }; }; DA12F33E0EF6E8BD00A40C6D /* blowUp.cpp */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {553, 1176}}"; sepNavSelRange = "{500, 0}"; sepNavVisRange = "{21, 621}"; sepNavWindowFrame = "{{204, 57}, {750, 558}}"; }; }; DA12F33F0EF6E8BD00A40C6D /* blowUp.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {691, 430}}"; sepNavSelRange = "{321, 0}"; sepNavVisRange = "{0, 325}"; sepNavWindowFrame = "{{38, 162}, {750, 558}}"; }; }; DA12F3400EF6E8BD00A40C6D /* common.cpp */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {553, 364}}"; sepNavSelRange = "{498, 0}"; sepNavVisRange = "{83, 460}"; }; }; DA12F3410EF6E8BD00A40C6D /* game.cpp */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {711, 21784}}"; sepNavSelRange = "{42027, 0}"; sepNavVisRange = "{8437, 165}"; sepNavWindowFrame = "{{202, 82}, {750, 558}}"; }; }; DA12F35D0EF6EB5E00A40C6D /* map.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = map.h; path = /Users/jasonrohrer/cpp/gamma256/gameSource/map.h; sourceTree = ""; }; DA12F3600EF6EB5E00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3610EF6EB5E00A40C6D /* landscape.h */; name = "landscape.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 692; vrLoc = 0; }; DA12F3610EF6EB5E00A40C6D /* landscape.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = landscape.h; path = /Users/jasonrohrer/cpp/gamma256/gameSource/landscape.h; sourceTree = ""; }; DA12F3620EF6EB5E00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3630EF6EB5E00A40C6D /* landscape.cpp */; name = "landscape.cpp: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 412; vrLoc = 0; }; DA12F3630EF6EB5E00A40C6D /* landscape.cpp */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = landscape.cpp; path = /Users/jasonrohrer/cpp/gamma256/gameSource/landscape.cpp; sourceTree = ""; }; DA12F3640EF6EB5E00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3650EF6EB5E00A40C6D /* HashTable.h */; name = "HashTable.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 424; vrLoc = 0; }; DA12F3650EF6EB5E00A40C6D /* HashTable.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HashTable.h; path = /Users/jasonrohrer/cpp/gamma256/gameSource/HashTable.h; sourceTree = ""; }; DA12F3660EF6EB5E00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3670EF6EB5E00A40C6D /* Envelope.h */; name = "Envelope.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 669; vrLoc = 0; }; DA12F3670EF6EB5E00A40C6D /* Envelope.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Envelope.h; path = /Users/jasonrohrer/cpp/gamma256/gameSource/Envelope.h; sourceTree = ""; }; DA12F3680EF6EB5E00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3690EF6EB5E00A40C6D /* Envelope.cpp */; name = "Envelope.cpp: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 723; vrLoc = 0; }; DA12F3690EF6EB5E00A40C6D /* Envelope.cpp */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Envelope.cpp; path = /Users/jasonrohrer/cpp/gamma256/gameSource/Envelope.cpp; sourceTree = ""; }; DA12F36D0EF6EB5E00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F36E0EF6EB5E00A40C6D /* World.h */; name = "World.h: 1"; rLen = 0; rLoc = 20; rType = 0; vrLen = 530; vrLoc = 0; }; DA12F36E0EF6EB5E00A40C6D /* World.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = World.h; path = /Users/jasonrohrer/cpp/gamma256/gameSource/World.h; sourceTree = ""; }; DA12F36F0EF6EB5E00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3700EF6EB5E00A40C6D /* World.cpp */; name = "World.cpp: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 307; vrLoc = 0; }; DA12F3700EF6EB5E00A40C6D /* World.cpp */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = World.cpp; path = /Users/jasonrohrer/cpp/gamma256/gameSource/World.cpp; sourceTree = ""; }; DA12F3710EF6EB5E00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3720EF6EB5E00A40C6D /* score.h */; name = "score.h: 1"; rLen = 0; rLoc = 20; rType = 0; vrLen = 215; vrLoc = 0; }; DA12F3720EF6EB5E00A40C6D /* score.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = score.h; path = /Users/jasonrohrer/cpp/gamma256/gameSource/score.h; sourceTree = ""; }; DA12F3730EF6EB5E00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3740EF6EB5E00A40C6D /* score.cpp */; name = "score.cpp: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 288; vrLoc = 0; }; DA12F3740EF6EB5E00A40C6D /* score.cpp */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = score.cpp; path = /Users/jasonrohrer/cpp/gamma256/gameSource/score.cpp; sourceTree = ""; }; DA12F3750EF6EB5E00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3760EF6EB5E00A40C6D /* map.h */; name = "map.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 541; vrLoc = 0; }; DA12F3760EF6EB5E00A40C6D /* map.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = map.h; path = /Users/jasonrohrer/cpp/gamma256/gameSource/map.h; sourceTree = ""; }; DA12F3770EF6EB5E00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3780EF6EB5E00A40C6D /* map.cpp */; name = "map.cpp: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 330; vrLoc = 0; }; DA12F3780EF6EB5E00A40C6D /* map.cpp */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = map.cpp; path = /Users/jasonrohrer/cpp/gamma256/gameSource/map.cpp; sourceTree = ""; }; DA12F3790EF6EB5E00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F37A0EF6EB5E00A40C6D /* landscape.h */; name = "landscape.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 692; vrLoc = 0; }; DA12F37A0EF6EB5E00A40C6D /* landscape.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = landscape.h; path = /Users/jasonrohrer/cpp/gamma256/gameSource/landscape.h; sourceTree = ""; }; DA12F37B0EF6EB5E00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F37C0EF6EB5E00A40C6D /* landscape.cpp */; name = "landscape.cpp: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 412; vrLoc = 0; }; DA12F37C0EF6EB5E00A40C6D /* landscape.cpp */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = landscape.cpp; path = /Users/jasonrohrer/cpp/gamma256/gameSource/landscape.cpp; sourceTree = ""; }; DA12F37D0EF6EB5E00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F37E0EF6EB5E00A40C6D /* HashTable.h */; name = "HashTable.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 424; vrLoc = 0; }; DA12F37E0EF6EB5E00A40C6D /* HashTable.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HashTable.h; path = /Users/jasonrohrer/cpp/gamma256/gameSource/HashTable.h; sourceTree = ""; }; DA12F37F0EF6EB5E00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3800EF6EB5E00A40C6D /* Envelope.h */; name = "Envelope.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 669; vrLoc = 0; }; DA12F3800EF6EB5E00A40C6D /* Envelope.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Envelope.h; path = /Users/jasonrohrer/cpp/gamma256/gameSource/Envelope.h; sourceTree = ""; }; DA12F3810EF6EB5E00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3820EF6EB5E00A40C6D /* Envelope.cpp */; name = "Envelope.cpp: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 723; vrLoc = 0; }; DA12F3820EF6EB5E00A40C6D /* Envelope.cpp */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Envelope.cpp; path = /Users/jasonrohrer/cpp/gamma256/gameSource/Envelope.cpp; sourceTree = ""; }; DA12F38A0EF6EB9F00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F35D0EF6EB5E00A40C6D /* map.h */; name = "map.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 541; vrLoc = 0; }; DA12F3A80EF6EDCA00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3720EF6EB5E00A40C6D /* score.h */; name = "score.h: 1"; rLen = 0; rLoc = 19; rType = 0; vrLen = 239; vrLoc = 0; }; DA12F3A90EF6EDCA00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3740EF6EB5E00A40C6D /* score.cpp */; name = "score.cpp: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 222; vrLoc = 0; }; DA12F3B30EF6EDCA00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3400EF6E8BD00A40C6D /* common.cpp */; name = "common.cpp: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 458; vrLoc = 0; }; DA12F3CC0EF6EEC700A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F33E0EF6E8BD00A40C6D /* blowUp.cpp */; name = "blowUp.cpp: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 550; vrLoc = 0; }; DA12F3CD0EF6EEC700A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F33F0EF6E8BD00A40C6D /* blowUp.h */; name = "blowUp.h: 1"; rLen = 0; rLoc = 27; rType = 0; vrLen = 282; vrLoc = 0; }; DA12F3CF0EF6EED000A40C6D /* common.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {553, 285}}"; sepNavSelRange = "{51, 38}"; sepNavVisRange = "{0, 252}"; }; }; DA12F3D90EF6EFFB00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F33F0EF6E8BD00A40C6D /* blowUp.h */; name = "blowUp.h: 1"; rLen = 0; rLoc = 27; rType = 0; vrLen = 310; vrLoc = 0; }; DA12F3DC0EF6EFFB00A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3CF0EF6EED000A40C6D /* common.h */; name = "common.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 252; vrLoc = 0; }; DA12F3F10EF6F1A100A40C6D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3410EF6E8BD00A40C6D /* game.cpp */; name = "game.cpp: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 388; vrLoc = 84; }; DA7F10EE0EF6CA2500CB6D50 /* drawIntoScreen.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {553, 322}}"; sepNavSelRange = "{509, 0}"; sepNavVisRange = "{50, 485}"; sepNavWindowFrame = "{{205, 93}, {750, 558}}"; }; }; DA7F10FB0EF6CCF600CB6D50 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA7F10EE0EF6CA2500CB6D50 /* drawIntoScreen.h */; name = "drawIntoScreen.h: 4"; rLen = 0; rLoc = 279; rType = 0; vrLen = 154; vrLoc = 0; }; DA7F117E0EF6D77000CB6D50 /* gameWindowAppDelegate.mm */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {553, 5950}}"; sepNavSelRange = "{8506, 0}"; sepNavVisRange = "{8370, 514}"; }; }; DA7F117F0EF6D77000CB6D50 /* gameWindowAppDelegate.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {714, 1050}}"; sepNavSelRange = "{1038, 0}"; sepNavVisRange = "{1193, 379}"; }; }; DA7F11800EF6D77000CB6D50 /* gameWindowApp_Prefix.pch */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {600, 262}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 195}"; }; }; DA7F11AD0EF6D9CB00CB6D50 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA7F11800EF6D77000CB6D50 /* gameWindowApp_Prefix.pch */; name = "gameWindowApp_Prefix.pch: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 195; vrLoc = 0; }; DA7F11AE0EF6D9CB00CB6D50 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA7F117F0EF6D77000CB6D50 /* gameWindowAppDelegate.h */; name = "gameWindowAppAppDelegate.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 387; vrLoc = 0; }; DA7F11B10EF6D9CB00CB6D50 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA7F117E0EF6D77000CB6D50 /* gameWindowAppDelegate.mm */; name = "gameWindowAppAppDelegate.mm: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 452; vrLoc = 0; }; DA7F12040EF6E3A400CB6D50 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA7F11800EF6D77000CB6D50 /* gameWindowApp_Prefix.pch */; name = "gameWindowApp_Prefix.pch: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 195; vrLoc = 0; }; DA8277520EF9FC240061079D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA7F10EE0EF6CA2500CB6D50 /* drawIntoScreen.h */; name = "drawIntoScreen.h: 21"; rLen = 0; rLoc = 509; rType = 0; vrLen = 485; vrLoc = 50; }; DA82779E0EFA03960061079D /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F3700EF6EB5E00A40C6D /* World.cpp */; name = "World.cpp: 23"; rLen = 0; rLoc = 312; rType = 0; vrLen = 571; vrLoc = 143; }; DA86AE6F0EF538E500054E6B /* Passage */ = { isa = PBXExecutable; activeArgIndices = ( ); argumentStrings = ( ); autoAttachOnCrash = 1; breakpointsEnabled = 0; configStateDict = { }; customDataFormattersEnabled = 1; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = ""; enableDebugStr = 1; environmentEntries = ( ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; libgmallocEnabled = 0; name = Passage; savedGlobals = { }; sourceDirectories = ( ); variableFormatDictionary = { }; }; DA86AE930EF5391600054E6B /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; scmConfiguration = { }; }; DA86AE940EF5391600054E6B /* Code sense */ = { isa = PBXCodeSenseManager; indexTemplatePath = ""; }; DA86AEB60EF53C5800054E6B /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 29B97316FDCFA39411CA2CEA /* main.m */; name = "main.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 368; vrLoc = 0; }; DA86AEE50EF53F3C00054E6B /* PlistBookmark */ = { isa = PlistBookmark; fRef = 8D1107310486CEB800E47090 /* Info.plist */; fallbackIsa = PBXBookmark; isK = 0; kPath = ( ); name = "/Volumes/Untitled 2/testWindowApp/Info.plist"; rLen = 0; rLoc = 2147483647; }; DA8C9E1B0EF8095C002FCA67 /* TimeUnix.cpp */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {553, 574}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 380}"; }; }; DA8C9E1D0EF80968002FCA67 /* ThreadLinux.cpp */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {553, 3430}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 545}"; }; }; DA8C9E1F0EF80985002FCA67 /* PathLinux.cpp */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {553, 1022}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 417}"; }; }; DA8C9E300EF809CA002FCA67 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA8C9E1B0EF8095C002FCA67 /* TimeUnix.cpp */; name = "TimeUnix.cpp: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 380; vrLoc = 0; }; DA8C9E310EF809CA002FCA67 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA8C9E1D0EF80968002FCA67 /* ThreadLinux.cpp */; name = "ThreadLinux.cpp: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 545; vrLoc = 0; }; DA8C9E320EF809CA002FCA67 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA8C9E1F0EF80985002FCA67 /* PathLinux.cpp */; name = "PathLinux.cpp: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 417; vrLoc = 0; }; DA8C9E560EF80B73002FCA67 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA8C9E1D0EF80968002FCA67 /* ThreadLinux.cpp */; name = "ThreadLinux.cpp: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 545; vrLoc = 0; }; DA8C9E5C0EF80B73002FCA67 /* unistd.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = unistd.h; path = /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator2.2.sdk/usr/include/unistd.h; sourceTree = ""; }; DA8C9E710EF80DA9002FCA67 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA8C9E5C0EF80B73002FCA67 /* unistd.h */; name = "unistd.h: 461"; rLen = 51; rLoc = 15908; rType = 0; vrLen = 674; vrLoc = 15562; }; DA8C9E730EF80DA9002FCA67 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA8C9E5C0EF80B73002FCA67 /* unistd.h */; name = "unistd.h: 461"; rLen = 51; rLoc = 15908; rType = 0; vrLen = 674; vrLoc = 15562; }; DA8C9E910EF810D7002FCA67 /* string.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = string.h; path = /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator2.2.sdk/usr/include/string.h; sourceTree = ""; }; DA8C9EAC0EF811E6002FCA67 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA8C9E910EF810D7002FCA67 /* string.h */; name = "string.h: 116"; rLen = 28; rLoc = 4727; rType = 0; vrLen = 760; vrLoc = 4173; }; DA8C9EAE0EF811E6002FCA67 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA8C9E910EF810D7002FCA67 /* string.h */; name = "string.h: 116"; rLen = 28; rLoc = 4727; rType = 0; vrLen = 760; vrLoc = 4173; }; DA8C9F4E0EF8266C002FCA67 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA8C9E1B0EF8095C002FCA67 /* TimeUnix.cpp */; name = "TimeUnix.cpp: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 380; vrLoc = 0; }; DA8C9F4F0EF8266C002FCA67 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA8C9E1F0EF80985002FCA67 /* PathLinux.cpp */; name = "PathLinux.cpp: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 417; vrLoc = 0; }; DA8C9F500EF8266C002FCA67 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F36E0EF6EB5E00A40C6D /* World.h */; name = "World.h: 1"; rLen = 19; rLoc = 0; rType = 0; vrLen = 510; vrLoc = 0; }; DA90DD050EFAB907001BABB5 /* musicPlayer.cpp */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {678, 11298}}"; sepNavSelRange = "{18324, 0}"; sepNavVisRange = "{18145, 879}"; sepNavWindowFrame = "{{15, 144}, {846, 597}}"; }; }; DA90DD110EFAC2AF001BABB5 /* Timbre.cpp */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {553, 2324}}"; sepNavSelRange = "{0, 0}"; sepNavVisRange = "{0, 362}"; }; }; DA90DD120EFAC2AF001BABB5 /* Timbre.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {787, 504}}"; sepNavSelRange = "{28, 0}"; sepNavVisRange = "{0, 1102}"; sepNavWindowFrame = "{{223, -30}, {846, 597}}"; }; }; DA90DDCD0EFAF5A3001BABB5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 29B97316FDCFA39411CA2CEA /* main.m */; name = "main.m: 22"; rLen = 0; rLoc = 447; rType = 0; vrLen = 661; vrLoc = 252; }; DA90DDCE0EFAF5A3001BABB5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA90DDCF0EFAF5A3001BABB5 /* stdint.h */; name = "stdint.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 402; vrLoc = 464; }; DA90DDCF0EFAF5A3001BABB5 /* stdint.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = stdint.h; path = /Developer/Platforms/iPhoneOS.platform/Developer/usr/include/gcc/darwin/4.0/stdint.h; sourceTree = ""; }; DA90DDD10EFAF5A3001BABB5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA90DD120EFAC2AF001BABB5 /* Timbre.h */; name = "Timbre.h: 1"; rLen = 43; rLoc = 0; rType = 0; vrLen = 728; vrLoc = 0; }; DA90DDD20EFAF5A3001BABB5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA90DDD30EFAF5A3001BABB5 /* AUComponent.h */; name = "AUComponent.h: 60"; rLen = 0; rLoc = 1369; rType = 0; vrLen = 534; vrLoc = 1246; }; DA90DDD30EFAF5A3001BABB5 /* AUComponent.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AUComponent.h; path = /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator2.2.sdk/System/Library/Frameworks/AudioUnit.framework/Headers/AUComponent.h; sourceTree = ""; }; DA90DDD50EFAF5A3001BABB5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA90DDD60EFAF5A3001BABB5 /* AUComponent.h */; name = "AUComponent.h: 67"; rLen = 31; rLoc = 1524; rType = 0; vrLen = 613; vrLoc = 1166; }; DA90DDD60EFAF5A3001BABB5 /* AUComponent.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AUComponent.h; path = /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.sdk/System/Library/Frameworks/AudioUnit.framework/Headers/AUComponent.h; sourceTree = ""; }; DA90DDD70EFAF5A3001BABB5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA90DD050EFAB907001BABB5 /* musicPlayer.cpp */; name = "musicPlayer.cpp: 637"; rLen = 0; rLoc = 18324; rType = 0; vrLen = 879; vrLoc = 18145; }; DA90DDDD0EFAF5A3001BABB5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA90DD050EFAB907001BABB5 /* musicPlayer.cpp */; name = "musicPlayer.cpp: 793"; rLen = 0; rLoc = 23411; rType = 0; vrLen = 620; vrLoc = 16250; }; DA90DDE00EFAF5A3001BABB5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA90DD120EFAC2AF001BABB5 /* Timbre.h */; name = "Timbre.h: 2"; rLen = 0; rLoc = 43; rType = 0; vrLen = 729; vrLoc = 0; }; DA90DDE10EFAF5A3001BABB5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA90DD110EFAC2AF001BABB5 /* Timbre.cpp */; name = "Timbre.cpp: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 435; vrLoc = 1669; }; DA90DDE90EFAF5A3001BABB5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA90DDEA0EFAF5A3001BABB5 /* stdint.h */; name = "stdint.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 402; vrLoc = 464; }; DA90DDEA0EFAF5A3001BABB5 /* stdint.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = stdint.h; path = /Developer/Platforms/iPhoneOS.platform/Developer/usr/include/gcc/darwin/4.0/stdint.h; sourceTree = ""; }; DA90DDEF0EFAF5A3001BABB5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA90DDF00EFAF5A3001BABB5 /* AUComponent.h */; name = "AUComponent.h: 60"; rLen = 0; rLoc = 1369; rType = 0; vrLen = 534; vrLoc = 1246; }; DA90DDF00EFAF5A3001BABB5 /* AUComponent.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AUComponent.h; path = /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator2.2.sdk/System/Library/Frameworks/AudioUnit.framework/Headers/AUComponent.h; sourceTree = ""; }; DA90DDF30EFAF5A3001BABB5 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA90DDF40EFAF5A3001BABB5 /* AUComponent.h */; name = "AUComponent.h: 67"; rLen = 31; rLoc = 1524; rType = 0; vrLen = 613; vrLoc = 1166; }; DA90DDF40EFAF5A3001BABB5 /* AUComponent.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AUComponent.h; path = /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.sdk/System/Library/Frameworks/AudioUnit.framework/Headers/AUComponent.h; sourceTree = ""; }; DA9E30CD0EFC240B00DFACC7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA12F33E0EF6E8BD00A40C6D /* blowUp.cpp */; name = "blowUp.cpp: 17"; rLen = 0; rLoc = 500; rType = 0; vrLen = 621; vrLoc = 21; }; DA9E30CF0EFC240B00DFACC7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA7F117F0EF6D77000CB6D50 /* gameWindowAppDelegate.h */; name = "gameWindowAppDelegate.h: 46"; rLen = 0; rLoc = 1038; rType = 0; vrLen = 379; vrLoc = 1193; }; DA9E30D00EFC240B00DFACC7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DA7F117E0EF6D77000CB6D50 /* gameWindowAppDelegate.mm */; name = "gameWindowAppDelegate.mm: 334"; rLen = 0; rLoc = 8506; rType = 0; vrLen = 514; vrLoc = 8370; }; DAADB67F0EF981DA00169CE3 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DAADB6800EF981DA00169CE3 /* UIAccelerometer.h */; name = "UIAccelerometer.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 535; vrLoc = 714; }; DAADB6800EF981DA00169CE3 /* UIAccelerometer.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = UIAccelerometer.h; path = /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator2.2.sdk/System/Library/Frameworks/UIKit.framework/Headers/UIAccelerometer.h; sourceTree = ""; }; DAADB6880EF981DA00169CE3 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = DAADB6890EF981DA00169CE3 /* UIAccelerometer.h */; name = "UIAccelerometer.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 535; vrLoc = 714; }; DAADB6890EF981DA00169CE3 /* UIAccelerometer.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = UIAccelerometer.h; path = /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator2.2.sdk/System/Library/Frameworks/UIKit.framework/Headers/UIAccelerometer.h; sourceTree = ""; }; } passage-4+dfsg1.orig/gamma256/gameSource/iPhone/gameWindowApp.xcodeproj/jasonrohrer.mode1v30000640000175000017500000012474611124755664030407 0ustar pabspabs ActivePerspectiveName Project AllowedModules BundleLoadPath MaxInstances n Module PBXSmartGroupTreeModule Name Groups and Files Outline View BundleLoadPath MaxInstances n Module PBXNavigatorGroup Name Editor BundleLoadPath MaxInstances n Module XCTaskListModule Name Task List BundleLoadPath MaxInstances n Module XCDetailModule Name File and Smart Group Detail Viewer BundleLoadPath MaxInstances 1 Module PBXBuildResultsModule Name Detailed Build Results Viewer BundleLoadPath MaxInstances 1 Module PBXProjectFindModule Name Project Batch Find Tool BundleLoadPath MaxInstances n Module XCProjectFormatConflictsModule Name Project Format Conflicts List BundleLoadPath MaxInstances n Module PBXBookmarksModule Name Bookmarks Tool BundleLoadPath MaxInstances n Module PBXClassBrowserModule Name Class Browser BundleLoadPath MaxInstances n Module PBXCVSModule Name Source Code Control Tool BundleLoadPath MaxInstances n Module PBXDebugBreakpointsModule Name Debug Breakpoints Tool BundleLoadPath MaxInstances n Module XCDockableInspector Name Inspector BundleLoadPath MaxInstances n Module PBXOpenQuicklyModule Name Open Quickly Tool BundleLoadPath MaxInstances 1 Module PBXDebugSessionModule Name Debugger BundleLoadPath MaxInstances 1 Module PBXDebugCLIModule Name Debug Console BundleLoadPath MaxInstances n Module XCSnapshotModule Name Snapshots Tool BundlePath /Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources Description DefaultDescriptionKey DockingSystemVisible Extension mode1v3 FavBarConfig PBXProjectModuleGUID DA86AEBF0EF53C5800054E6B XCBarModuleItemNames XCBarModuleItems FirstTimeWindowDisplayed Identifier com.apple.perspectives.project.mode1v3 MajorVersion 33 MinorVersion 0 Name Default Notifications OpenEditors PerspectiveWidths -1 -1 Perspectives ChosenToolbarItems active-combo-popup action NSToolbarFlexibleSpaceItem build-and-go com.apple.ide.PBXToolbarStopButton get-info NSToolbarFlexibleSpaceItem com.apple.pbx.toolbar.searchfield ControllerClassBaseName IconName WindowOfProjectWithEditor Identifier perspective.project IsVertical Layout BecomeActive ContentConfiguration PBXBottomSmartGroupGIDs 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C08E77C0454961000C914BD 1C37FABC05509CD000000102 1C37FABC05539CD112110102 E2644B35053B69B200211256 1C37FABC04509CD000100104 1CC0EA4004350EF90044410B 1CC0EA4004350EF90041110B PBXProjectModuleGUID 1CE0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided yes PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 270 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 29B97314FDCFA39411CA2CEA 080E96DDFE201D6D7F000001 29B97315FDCFA39411CA2CEA DA12F31E0EF6E84900A40C6D DA12F31D0EF6E83D00A40C6D 29B97317FDCFA39411CA2CEA 19C28FACFE9D520D11CA2CBB 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C37FABC05509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey 35 31 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 305}, {270, 477}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch XCSharingToken com.apple.Xcode.GFSharingToken GeometryConfiguration Frame {{0, 0}, {287, 495}} GroupTreeTableConfiguration MainColumn 270 RubberWindowFrame 16 135 906 536 0 0 1024 746 Module PBXSmartGroupTreeModule Proportion 287pt Dock ContentConfiguration PBXProjectModuleGUID 1CE0B20306471E060097A5F4 PBXProjectModuleLabel Info.plist PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1CE0B20406471E060097A5F4 PBXProjectModuleLabel Info.plist _historyCapacity 0 bookmark DA0EC6610F0412F800DC5B33 history DA7F12040EF6E3A400CB6D50 DA12F3600EF6EB5E00A40C6D DA12F3620EF6EB5E00A40C6D DA12F3640EF6EB5E00A40C6D DA12F3660EF6EB5E00A40C6D DA12F3680EF6EB5E00A40C6D DA12F38A0EF6EB9F00A40C6D DA12F3A80EF6EDCA00A40C6D DA12F3A90EF6EDCA00A40C6D DA12F3D90EF6EFFB00A40C6D DA8C9E560EF80B73002FCA67 DA8C9E710EF80DA9002FCA67 DA8C9EAC0EF811E6002FCA67 DA8C9F4E0EF8266C002FCA67 DA8C9F4F0EF8266C002FCA67 DA8C9F500EF8266C002FCA67 DAADB67F0EF981DA00169CE3 DA8277520EF9FC240061079D DA82779E0EFA03960061079D DA90DDCD0EFAF5A3001BABB5 DA90DDCE0EFAF5A3001BABB5 DA90DDD10EFAF5A3001BABB5 DA90DDD20EFAF5A3001BABB5 DA90DDD50EFAF5A3001BABB5 DA90DDD70EFAF5A3001BABB5 DA9E30CD0EFC240B00DFACC7 DA9E30CF0EFC240B00DFACC7 DA9E30D00EFC240B00DFACC7 DA0EC5C40F03E66500DC5B33 DA0EC60E0F03FE7400DC5B33 DA0EC6190F04026C00DC5B33 DA0EC64F0F0412E300DC5B33 DA0EC65F0F0412F800DC5B33 DA0EC6500F0412E300DC5B33 prevStack DA86AEB60EF53C5800054E6B DA86AEE50EF53F3C00054E6B DA7F10FB0EF6CCF600CB6D50 DA7F11AD0EF6D9CB00CB6D50 DA7F11AE0EF6D9CB00CB6D50 DA7F11B10EF6D9CB00CB6D50 DA12F36D0EF6EB5E00A40C6D DA12F36F0EF6EB5E00A40C6D DA12F3710EF6EB5E00A40C6D DA12F3730EF6EB5E00A40C6D DA12F3750EF6EB5E00A40C6D DA12F3770EF6EB5E00A40C6D DA12F3790EF6EB5E00A40C6D DA12F37B0EF6EB5E00A40C6D DA12F37D0EF6EB5E00A40C6D DA12F37F0EF6EB5E00A40C6D DA12F3810EF6EB5E00A40C6D DA12F3B30EF6EDCA00A40C6D DA12F3CC0EF6EEC700A40C6D DA12F3CD0EF6EEC700A40C6D DA12F3DC0EF6EFFB00A40C6D DA12F3F10EF6F1A100A40C6D DA8C9E300EF809CA002FCA67 DA8C9E310EF809CA002FCA67 DA8C9E320EF809CA002FCA67 DA8C9E730EF80DA9002FCA67 DA8C9EAE0EF811E6002FCA67 DAADB6880EF981DA00169CE3 DA90DDDD0EFAF5A3001BABB5 DA90DDE00EFAF5A3001BABB5 DA90DDE10EFAF5A3001BABB5 DA90DDE90EFAF5A3001BABB5 DA90DDEF0EFAF5A3001BABB5 DA90DDF30EFAF5A3001BABB5 DA0EC6600F0412F800DC5B33 SplitCount 1 StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {614, 317}} RubberWindowFrame 16 135 906 536 0 0 1024 746 Module PBXNavigatorGroup Proportion 317pt ContentConfiguration PBXProjectModuleGUID 1CE0B20506471E060097A5F4 PBXProjectModuleLabel Detail GeometryConfiguration Frame {{0, 322}, {614, 173}} RubberWindowFrame 16 135 906 536 0 0 1024 746 Module XCDetailModule Proportion 173pt Proportion 614pt Name Project ServiceClasses XCModuleDock PBXSmartGroupTreeModule XCModuleDock PBXNavigatorGroup XCDetailModule TableOfContents DA0EC6620F0412F800DC5B33 1CE0B1FE06471DED0097A5F4 DA0EC6630F0412F800DC5B33 1CE0B20306471E060097A5F4 1CE0B20506471E060097A5F4 ToolbarConfiguration xcode.toolbar.config.defaultV3 ControllerClassBaseName IconName WindowOfProject Identifier perspective.morph IsVertical 0 Layout BecomeActive 1 ContentConfiguration PBXBottomSmartGroupGIDs 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C08E77C0454961000C914BD 1C37FABC05509CD000000102 1C37FABC05539CD112110102 E2644B35053B69B200211256 1C37FABC04509CD000100104 1CC0EA4004350EF90044410B 1CC0EA4004350EF90041110B PBXProjectModuleGUID 11E0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided yes PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 186 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 29B97314FDCFA39411CA2CEA 1C37FABC05509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {186, 337}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch 1 XCSharingToken com.apple.Xcode.GFSharingToken GeometryConfiguration Frame {{0, 0}, {203, 355}} GroupTreeTableConfiguration MainColumn 186 RubberWindowFrame 373 269 690 397 0 0 1440 878 Module PBXSmartGroupTreeModule Proportion 100% Name Morph PreferredWidth 300 ServiceClasses XCModuleDock PBXSmartGroupTreeModule TableOfContents 11E0B1FE06471DED0097A5F4 ToolbarConfiguration xcode.toolbar.config.default.shortV3 PerspectivesBarVisible ShelfIsVisible SourceDescription file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecificationMode1.xcperspec' StatusbarIsVisible TimeStamp 0.0 ToolbarDisplayMode 1 ToolbarIsVisible ToolbarSizeMode 1 Type Perspectives UpdateMessage The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'? WindowJustification 5 WindowOrderList /Users/jasonrohrer/cpp/gamma256/gameSource/iPhone/gameWindowApp.xcodeproj WindowString 16 135 906 536 0 0 1024 746 WindowToolsV3 FirstTimeWindowDisplayed Identifier windowTool.build IsVertical Layout Dock ContentConfiguration PBXProjectModuleGUID 1CD0528F0623707200166675 PBXProjectModuleLabel StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {772, 95}} RubberWindowFrame 191 148 772 506 0 0 1024 746 Module PBXNavigatorGroup Proportion 95pt BecomeActive ContentConfiguration PBXBuildLogShowsTranscriptDefaultKey {{0, 5}, {772, 360}} PBXProjectModuleGUID XCMainBuildResultsModuleGUID PBXProjectModuleLabel Build XCBuildResultsTrigger_Collapse 1021 XCBuildResultsTrigger_Open 1011 GeometryConfiguration Frame {{0, 100}, {772, 365}} RubberWindowFrame 191 148 772 506 0 0 1024 746 Module PBXBuildResultsModule Proportion 365pt Proportion 465pt Name Build Results ServiceClasses PBXBuildResultsModule StatusbarIsVisible TableOfContents DA86AEC00EF53C5800054E6B DA0EC6460F04124700DC5B33 1CD0528F0623707200166675 XCMainBuildResultsModuleGUID ToolbarConfiguration xcode.toolbar.config.buildV3 WindowString 191 148 772 506 0 0 1024 746 WindowToolGUID DA86AEC00EF53C5800054E6B WindowToolIsVisible FirstTimeWindowDisplayed Identifier windowTool.debugger IsVertical Layout Dock ContentConfiguration Debugger HorizontalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {316, 203}} {{316, 0}, {378, 203}} VerticalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {694, 203}} {{0, 203}, {694, 178}} LauncherConfigVersion 8 PBXProjectModuleGUID 1C162984064C10D400B95A72 PBXProjectModuleLabel Debug - GLUTExamples (Underwater) GeometryConfiguration DebugConsoleVisible None DebugConsoleWindowFrame {{200, 200}, {500, 300}} DebugSTDIOWindowFrame {{200, 200}, {500, 300}} Frame {{0, 0}, {694, 381}} PBXDebugSessionStackFrameViewKey DebugVariablesTableConfiguration Name 120 Value 85 Summary 148 Frame {{316, 0}, {378, 203}} RubberWindowFrame 128 288 694 422 0 0 1024 746 RubberWindowFrame 128 288 694 422 0 0 1024 746 Module PBXDebugSessionModule Proportion 381pt Proportion 381pt Name Debugger ServiceClasses PBXDebugSessionModule StatusbarIsVisible TableOfContents 1CD10A99069EF8BA00B06720 DA0EC6470F04124700DC5B33 1C162984064C10D400B95A72 DA0EC6480F04124700DC5B33 DA0EC6490F04124700DC5B33 DA0EC64A0F04124700DC5B33 DA0EC64B0F04124700DC5B33 DA0EC64C0F04124700DC5B33 ToolbarConfiguration xcode.toolbar.config.debugV3 WindowString 128 288 694 422 0 0 1024 746 WindowToolGUID 1CD10A99069EF8BA00B06720 WindowToolIsVisible FirstTimeWindowDisplayed Identifier windowTool.find IsVertical Layout Dock Dock ContentConfiguration PBXProjectModuleGUID 1CDD528C0622207200134675 PBXProjectModuleLabel StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {781, 212}} RubberWindowFrame 69 170 781 470 0 0 1024 746 Module PBXNavigatorGroup Proportion 781pt Proportion 212pt BecomeActive ContentConfiguration PBXProjectModuleGUID 1CD0528E0623707200166675 PBXProjectModuleLabel Project Find GeometryConfiguration Frame {{0, 217}, {781, 212}} RubberWindowFrame 69 170 781 470 0 0 1024 746 Module PBXProjectFindModule Proportion 212pt Proportion 429pt Name Project Find ServiceClasses PBXProjectFindModule StatusbarIsVisible TableOfContents 1C530D57069F1CE1000CFCEE DA7F11390EF6D2EE00CB6D50 DA7F113A0EF6D2EE00CB6D50 1CDD528C0622207200134675 1CD0528E0623707200166675 WindowString 69 170 781 470 0 0 1024 746 WindowToolGUID 1C530D57069F1CE1000CFCEE WindowToolIsVisible Identifier MENUSEPARATOR FirstTimeWindowDisplayed Identifier windowTool.debuggerConsole IsVertical Layout Dock ContentConfiguration PBXProjectModuleGUID 1C78EAAC065D492600B07095 PBXProjectModuleLabel Debugger Console GeometryConfiguration Frame {{0, 0}, {655, 370}} RubberWindowFrame 17 141 655 411 0 0 1024 746 Module PBXDebugCLIModule Proportion 370pt Proportion 370pt Name Debugger Console ServiceClasses PBXDebugCLIModule StatusbarIsVisible TableOfContents 1C78EAAD065D492600B07095 DA0EC64D0F04124700DC5B33 1C78EAAC065D492600B07095 ToolbarConfiguration xcode.toolbar.config.consoleV3 WindowString 17 141 655 411 0 0 1024 746 WindowToolGUID 1C78EAAD065D492600B07095 WindowToolIsVisible Identifier windowTool.snapshots Layout Dock Module XCSnapshotModule Proportion 100% Proportion 100% Name Snapshots ServiceClasses XCSnapshotModule StatusbarIsVisible Yes ToolbarConfiguration xcode.toolbar.config.snapshots WindowString 315 824 300 550 0 0 1440 878 WindowToolIsVisible Yes Identifier windowTool.scm Layout Dock ContentConfiguration PBXProjectModuleGUID 1C78EAB2065D492600B07095 PBXProjectModuleLabel <No Editor> PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1C78EAB3065D492600B07095 SplitCount 1 StatusBarVisibility 1 GeometryConfiguration Frame {{0, 0}, {452, 0}} RubberWindowFrame 743 379 452 308 0 0 1280 1002 Module PBXNavigatorGroup Proportion 0pt BecomeActive 1 ContentConfiguration PBXProjectModuleGUID 1CD052920623707200166675 PBXProjectModuleLabel SCM GeometryConfiguration ConsoleFrame {{0, 259}, {452, 0}} Frame {{0, 7}, {452, 259}} RubberWindowFrame 743 379 452 308 0 0 1280 1002 TableConfiguration Status 30 FileName 199 Path 197.0950012207031 TableFrame {{0, 0}, {452, 250}} Module PBXCVSModule Proportion 262pt Proportion 266pt Name SCM ServiceClasses PBXCVSModule StatusbarIsVisible 1 TableOfContents 1C78EAB4065D492600B07095 1C78EAB5065D492600B07095 1C78EAB2065D492600B07095 1CD052920623707200166675 ToolbarConfiguration xcode.toolbar.config.scm WindowString 743 379 452 308 0 0 1280 1002 Identifier windowTool.breakpoints IsVertical 0 Layout Dock BecomeActive 1 ContentConfiguration PBXBottomSmartGroupGIDs 1C77FABC04509CD000000102 PBXProjectModuleGUID 1CE0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided no PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 168 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 1C77FABC04509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {168, 350}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch 0 GeometryConfiguration Frame {{0, 0}, {185, 368}} GroupTreeTableConfiguration MainColumn 168 RubberWindowFrame 315 424 744 409 0 0 1440 878 Module PBXSmartGroupTreeModule Proportion 185pt ContentConfiguration PBXProjectModuleGUID 1CA1AED706398EBD00589147 PBXProjectModuleLabel Detail GeometryConfiguration Frame {{190, 0}, {554, 368}} RubberWindowFrame 315 424 744 409 0 0 1440 878 Module XCDetailModule Proportion 554pt Proportion 368pt MajorVersion 3 MinorVersion 0 Name Breakpoints ServiceClasses PBXSmartGroupTreeModule XCDetailModule StatusbarIsVisible 1 TableOfContents 1CDDB66807F98D9800BB5817 1CDDB66907F98D9800BB5817 1CE0B1FE06471DED0097A5F4 1CA1AED706398EBD00589147 ToolbarConfiguration xcode.toolbar.config.breakpointsV3 WindowString 315 424 744 409 0 0 1440 878 WindowToolGUID 1CDDB66807F98D9800BB5817 WindowToolIsVisible 1 Identifier windowTool.debugAnimator Layout Dock Module PBXNavigatorGroup Proportion 100% Proportion 100% Name Debug Visualizer ServiceClasses PBXNavigatorGroup StatusbarIsVisible 1 ToolbarConfiguration xcode.toolbar.config.debugAnimatorV3 WindowString 100 100 700 500 0 0 1280 1002 Identifier windowTool.bookmarks Layout Dock Module PBXBookmarksModule Proportion 100% Proportion 100% Name Bookmarks ServiceClasses PBXBookmarksModule StatusbarIsVisible 0 WindowString 538 42 401 187 0 0 1280 1002 Identifier windowTool.projectFormatConflicts Layout Dock Module XCProjectFormatConflictsModule Proportion 100% Proportion 100% Name Project Format Conflicts ServiceClasses XCProjectFormatConflictsModule StatusbarIsVisible 0 WindowContentMinSize 450 300 WindowString 50 850 472 307 0 0 1440 877 Identifier windowTool.classBrowser Layout Dock BecomeActive 1 ContentConfiguration OptionsSetName Hierarchy, all classes PBXProjectModuleGUID 1CA6456E063B45B4001379D8 PBXProjectModuleLabel Class Browser - NSObject GeometryConfiguration ClassesFrame {{0, 0}, {374, 96}} ClassesTreeTableConfiguration PBXClassNameColumnIdentifier 208 PBXClassBookColumnIdentifier 22 Frame {{0, 0}, {630, 331}} MembersFrame {{0, 105}, {374, 395}} MembersTreeTableConfiguration PBXMemberTypeIconColumnIdentifier 22 PBXMemberNameColumnIdentifier 216 PBXMemberTypeColumnIdentifier 97 PBXMemberBookColumnIdentifier 22 PBXModuleWindowStatusBarHidden2 1 RubberWindowFrame 385 179 630 352 0 0 1440 878 Module PBXClassBrowserModule Proportion 332pt Proportion 332pt Name Class Browser ServiceClasses PBXClassBrowserModule StatusbarIsVisible 0 TableOfContents 1C0AD2AF069F1E9B00FABCE6 1C0AD2B0069F1E9B00FABCE6 1CA6456E063B45B4001379D8 ToolbarConfiguration xcode.toolbar.config.classbrowser WindowString 385 179 630 352 0 0 1440 878 WindowToolGUID 1C0AD2AF069F1E9B00FABCE6 WindowToolIsVisible 0 Identifier windowTool.refactoring IncludeInToolsMenu 0 Layout Dock BecomeActive 1 GeometryConfiguration Frame {0, 0}, {500, 335} RubberWindowFrame {0, 0}, {500, 335} Module XCRefactoringModule Proportion 100% Proportion 100% Name Refactoring ServiceClasses XCRefactoringModule WindowString 200 200 500 356 0 0 1920 1200 passage-4+dfsg1.orig/gamma256/gameSource/iPhone/gameWindowApp.xcodeproj/project.pbxproj0000750000175000017500000006755111122776140027717 0ustar pabspabs// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 45; objects = { /* Begin PBXBuildFile section */ 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; DA12F3060EF6E70100A40C6D /* title.tga in Resources */ = {isa = PBXBuildFile; fileRef = DA12F2FC0EF6E70100A40C6D /* title.tga */; }; DA12F3070EF6E70100A40C6D /* heart.tga in Resources */ = {isa = PBXBuildFile; fileRef = DA12F2FD0EF6E70100A40C6D /* heart.tga */; }; DA12F3080EF6E70100A40C6D /* numerals.tga in Resources */ = {isa = PBXBuildFile; fileRef = DA12F2FE0EF6E70100A40C6D /* numerals.tga */; }; DA12F3090EF6E70100A40C6D /* spouseSprite.tga in Resources */ = {isa = PBXBuildFile; fileRef = DA12F2FF0EF6E70100A40C6D /* spouseSprite.tga */; }; DA12F30A0EF6E70100A40C6D /* tileSet.tga in Resources */ = {isa = PBXBuildFile; fileRef = DA12F3000EF6E70100A40C6D /* tileSet.tga */; }; DA12F30B0EF6E70100A40C6D /* chestPrize.tga in Resources */ = {isa = PBXBuildFile; fileRef = DA12F3010EF6E70100A40C6D /* chestPrize.tga */; }; DA12F30C0EF6E70100A40C6D /* chestDust.tga in Resources */ = {isa = PBXBuildFile; fileRef = DA12F3020EF6E70100A40C6D /* chestDust.tga */; }; DA12F30D0EF6E70100A40C6D /* chest.tga in Resources */ = {isa = PBXBuildFile; fileRef = DA12F3030EF6E70100A40C6D /* chest.tga */; }; DA12F30E0EF6E70100A40C6D /* characterSpriteSad.tga in Resources */ = {isa = PBXBuildFile; fileRef = DA12F3040EF6E70100A40C6D /* characterSpriteSad.tga */; }; DA12F30F0EF6E70100A40C6D /* characterSprite.tga in Resources */ = {isa = PBXBuildFile; fileRef = DA12F3050EF6E70100A40C6D /* characterSprite.tga */; }; DA12F3390EF6E89F00A40C6D /* World.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA12F32E0EF6E89F00A40C6D /* World.cpp */; }; DA12F33A0EF6E89F00A40C6D /* score.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA12F3300EF6E89F00A40C6D /* score.cpp */; }; DA12F33B0EF6E89F00A40C6D /* map.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA12F3320EF6E89F00A40C6D /* map.cpp */; }; DA12F33C0EF6E89F00A40C6D /* landscape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA12F3340EF6E89F00A40C6D /* landscape.cpp */; }; DA12F33D0EF6E89F00A40C6D /* Envelope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA12F3370EF6E89F00A40C6D /* Envelope.cpp */; }; DA12F3420EF6E8BD00A40C6D /* blowUp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA12F33E0EF6E8BD00A40C6D /* blowUp.cpp */; }; DA12F3430EF6E8BD00A40C6D /* common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA12F3400EF6E8BD00A40C6D /* common.cpp */; }; DA12F3440EF6E8BD00A40C6D /* game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA12F3410EF6E8BD00A40C6D /* game.cpp */; }; DA12F3E60EF6F00600A40C6D /* music.tga in Resources */ = {isa = PBXBuildFile; fileRef = DA12F3E50EF6F00600A40C6D /* music.tga */; }; DA7F11810EF6D77000CB6D50 /* gameWindowAppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA7F117E0EF6D77000CB6D50 /* gameWindowAppDelegate.mm */; }; DA8276E60EF9B2290061079D /* arrows.tga in Resources */ = {isa = PBXBuildFile; fileRef = DA8276E50EF9B2290061079D /* arrows.tga */; }; DA8277840EF9FFE80061079D /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8277830EF9FFE80061079D /* Icon.png */; }; DA86AEC90EF53C7100054E6B /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; DA8C9E1C0EF8095C002FCA67 /* TimeUnix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA8C9E1B0EF8095C002FCA67 /* TimeUnix.cpp */; }; DA8C9E1E0EF80968002FCA67 /* ThreadLinux.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA8C9E1D0EF80968002FCA67 /* ThreadLinux.cpp */; }; DA8C9E200EF80985002FCA67 /* PathLinux.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA8C9E1F0EF80985002FCA67 /* PathLinux.cpp */; }; DA8C9F090EF817F7002FCA67 /* StringBufferOutputStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA8C9F050EF817F7002FCA67 /* StringBufferOutputStream.cpp */; }; DA8C9F0A0EF817F7002FCA67 /* stringUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA8C9F070EF817F7002FCA67 /* stringUtils.cpp */; }; DA90DD060EFAB907001BABB5 /* musicPlayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA90DD050EFAB907001BABB5 /* musicPlayer.cpp */; }; DA90DD140EFAC2AF001BABB5 /* Timbre.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DA90DD110EFAC2AF001BABB5 /* Timbre.cpp */; }; DA90DD4A0EFADE15001BABB5 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA90DD490EFADE15001BABB5 /* AudioToolbox.framework */; }; DA9E302E0EFC010300DFACC7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA9E302C0EFC010300DFACC7 /* QuartzCore.framework */; }; DA9E302F0EFC010300DFACC7 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA9E302D0EFC010300DFACC7 /* OpenGLES.framework */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 1D6058910D05DD3D006BFB54 /* Passage.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Passage.app; sourceTree = BUILT_PRODUCTS_DIR; }; 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 28AD733E0D9D9553002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; DA12F2FC0EF6E70100A40C6D /* title.tga */ = {isa = PBXFileReference; lastKnownFileType = file; name = title.tga; path = ../graphics/title.tga; sourceTree = SOURCE_ROOT; }; DA12F2FD0EF6E70100A40C6D /* heart.tga */ = {isa = PBXFileReference; lastKnownFileType = file; name = heart.tga; path = ../graphics/heart.tga; sourceTree = SOURCE_ROOT; }; DA12F2FE0EF6E70100A40C6D /* numerals.tga */ = {isa = PBXFileReference; lastKnownFileType = file; name = numerals.tga; path = ../graphics/numerals.tga; sourceTree = SOURCE_ROOT; }; DA12F2FF0EF6E70100A40C6D /* spouseSprite.tga */ = {isa = PBXFileReference; lastKnownFileType = file; name = spouseSprite.tga; path = ../graphics/spouseSprite.tga; sourceTree = SOURCE_ROOT; }; DA12F3000EF6E70100A40C6D /* tileSet.tga */ = {isa = PBXFileReference; lastKnownFileType = file; name = tileSet.tga; path = ../graphics/tileSet.tga; sourceTree = SOURCE_ROOT; }; DA12F3010EF6E70100A40C6D /* chestPrize.tga */ = {isa = PBXFileReference; lastKnownFileType = file; name = chestPrize.tga; path = ../graphics/chestPrize.tga; sourceTree = SOURCE_ROOT; }; DA12F3020EF6E70100A40C6D /* chestDust.tga */ = {isa = PBXFileReference; lastKnownFileType = file; name = chestDust.tga; path = ../graphics/chestDust.tga; sourceTree = SOURCE_ROOT; }; DA12F3030EF6E70100A40C6D /* chest.tga */ = {isa = PBXFileReference; lastKnownFileType = file; name = chest.tga; path = ../graphics/chest.tga; sourceTree = SOURCE_ROOT; }; DA12F3040EF6E70100A40C6D /* characterSpriteSad.tga */ = {isa = PBXFileReference; lastKnownFileType = file; name = characterSpriteSad.tga; path = ../graphics/characterSpriteSad.tga; sourceTree = SOURCE_ROOT; }; DA12F3050EF6E70100A40C6D /* characterSprite.tga */ = {isa = PBXFileReference; lastKnownFileType = file; name = characterSprite.tga; path = ../graphics/characterSprite.tga; sourceTree = SOURCE_ROOT; }; DA12F32D0EF6E89F00A40C6D /* World.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = World.h; path = ../World.h; sourceTree = SOURCE_ROOT; }; DA12F32E0EF6E89F00A40C6D /* World.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = World.cpp; path = ../World.cpp; sourceTree = SOURCE_ROOT; }; DA12F32F0EF6E89F00A40C6D /* score.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = score.h; path = ../score.h; sourceTree = SOURCE_ROOT; }; DA12F3300EF6E89F00A40C6D /* score.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = score.cpp; path = ../score.cpp; sourceTree = SOURCE_ROOT; }; DA12F3310EF6E89F00A40C6D /* map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = map.h; path = ../map.h; sourceTree = SOURCE_ROOT; }; DA12F3320EF6E89F00A40C6D /* map.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = map.cpp; path = ../map.cpp; sourceTree = SOURCE_ROOT; }; DA12F3330EF6E89F00A40C6D /* landscape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = landscape.h; path = ../landscape.h; sourceTree = SOURCE_ROOT; }; DA12F3340EF6E89F00A40C6D /* landscape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = landscape.cpp; path = ../landscape.cpp; sourceTree = SOURCE_ROOT; }; DA12F3350EF6E89F00A40C6D /* HashTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HashTable.h; path = ../HashTable.h; sourceTree = SOURCE_ROOT; }; DA12F3360EF6E89F00A40C6D /* Envelope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Envelope.h; path = ../Envelope.h; sourceTree = SOURCE_ROOT; }; DA12F3370EF6E89F00A40C6D /* Envelope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Envelope.cpp; path = ../Envelope.cpp; sourceTree = SOURCE_ROOT; }; DA12F33E0EF6E8BD00A40C6D /* blowUp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = blowUp.cpp; sourceTree = ""; }; DA12F33F0EF6E8BD00A40C6D /* blowUp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blowUp.h; sourceTree = ""; }; DA12F3400EF6E8BD00A40C6D /* common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = common.cpp; sourceTree = ""; }; DA12F3410EF6E8BD00A40C6D /* game.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = game.cpp; sourceTree = ""; }; DA12F3CF0EF6EED000A40C6D /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = common.h; path = ../common.h; sourceTree = SOURCE_ROOT; }; DA12F3E50EF6F00600A40C6D /* music.tga */ = {isa = PBXFileReference; lastKnownFileType = file; name = music.tga; path = ../music/music.tga; sourceTree = SOURCE_ROOT; }; DA7F10EE0EF6CA2500CB6D50 /* drawIntoScreen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = drawIntoScreen.h; sourceTree = ""; }; DA7F117E0EF6D77000CB6D50 /* gameWindowAppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = gameWindowAppDelegate.mm; sourceTree = ""; }; DA7F117F0EF6D77000CB6D50 /* gameWindowAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gameWindowAppDelegate.h; sourceTree = ""; }; DA7F11800EF6D77000CB6D50 /* gameWindowApp_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gameWindowApp_Prefix.pch; sourceTree = ""; }; DA8276E50EF9B2290061079D /* arrows.tga */ = {isa = PBXFileReference; lastKnownFileType = file; path = arrows.tga; sourceTree = ""; }; DA8277830EF9FFE80061079D /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = ""; }; DA8C9E1B0EF8095C002FCA67 /* TimeUnix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TimeUnix.cpp; path = ../../../minorGems/system/unix/TimeUnix.cpp; sourceTree = SOURCE_ROOT; }; DA8C9E1D0EF80968002FCA67 /* ThreadLinux.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadLinux.cpp; path = ../../../minorGems/system/linux/ThreadLinux.cpp; sourceTree = SOURCE_ROOT; }; DA8C9E1F0EF80985002FCA67 /* PathLinux.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PathLinux.cpp; path = ../../../minorGems/io/file/linux/PathLinux.cpp; sourceTree = SOURCE_ROOT; }; DA8C9F050EF817F7002FCA67 /* StringBufferOutputStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringBufferOutputStream.cpp; path = ../../../minorGems/util/StringBufferOutputStream.cpp; sourceTree = SOURCE_ROOT; }; DA8C9F060EF817F7002FCA67 /* StringBufferOutputStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringBufferOutputStream.h; path = ../../../minorGems/util/StringBufferOutputStream.h; sourceTree = SOURCE_ROOT; }; DA8C9F070EF817F7002FCA67 /* stringUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stringUtils.cpp; path = ../../../minorGems/util/stringUtils.cpp; sourceTree = SOURCE_ROOT; }; DA8C9F080EF817F7002FCA67 /* stringUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stringUtils.h; path = ../../../minorGems/util/stringUtils.h; sourceTree = SOURCE_ROOT; }; DA90DD050EFAB907001BABB5 /* musicPlayer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = musicPlayer.cpp; sourceTree = ""; }; DA90DD110EFAC2AF001BABB5 /* Timbre.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Timbre.cpp; path = ../Timbre.cpp; sourceTree = SOURCE_ROOT; }; DA90DD120EFAC2AF001BABB5 /* Timbre.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Timbre.h; path = ../Timbre.h; sourceTree = SOURCE_ROOT; }; DA90DD130EFAC2AF001BABB5 /* musicPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = musicPlayer.h; path = ../musicPlayer.h; sourceTree = SOURCE_ROOT; }; DA90DD490EFADE15001BABB5 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; DA9E302C0EFC010300DFACC7 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; DA9E302D0EFC010300DFACC7 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, DA90DD4A0EFADE15001BABB5 /* AudioToolbox.framework in Frameworks */, DA9E302E0EFC010300DFACC7 /* QuartzCore.framework in Frameworks */, DA9E302F0EFC010300DFACC7 /* OpenGLES.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( ); path = Classes; sourceTree = ""; }; 19C28FACFE9D520D11CA2CBB /* Products */ = { isa = PBXGroup; children = ( 1D6058910D05DD3D006BFB54 /* Passage.app */, ); name = Products; sourceTree = ""; }; 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { isa = PBXGroup; children = ( 080E96DDFE201D6D7F000001 /* Classes */, 29B97315FDCFA39411CA2CEA /* Other Sources */, 29B97317FDCFA39411CA2CEA /* Resources */, 29B97323FDCFA39411CA2CEA /* Frameworks */, 19C28FACFE9D520D11CA2CBB /* Products */, ); name = CustomTemplate; sourceTree = ""; }; 29B97315FDCFA39411CA2CEA /* Other Sources */ = { isa = PBXGroup; children = ( DA12F31E0EF6E84900A40C6D /* Unchanged */, DA12F31D0EF6E83D00A40C6D /* Customized */, DA7F117E0EF6D77000CB6D50 /* gameWindowAppDelegate.mm */, DA7F117F0EF6D77000CB6D50 /* gameWindowAppDelegate.h */, DA7F11800EF6D77000CB6D50 /* gameWindowApp_Prefix.pch */, DA7F10EE0EF6CA2500CB6D50 /* drawIntoScreen.h */, 29B97316FDCFA39411CA2CEA /* main.m */, ); name = "Other Sources"; sourceTree = ""; }; 29B97317FDCFA39411CA2CEA /* Resources */ = { isa = PBXGroup; children = ( DA8277830EF9FFE80061079D /* Icon.png */, DA12F2FB0EF6E6B100A40C6D /* graphics */, 28AD733E0D9D9553002E5188 /* MainWindow.xib */, 8D1107310486CEB800E47090 /* Info.plist */, ); name = Resources; sourceTree = ""; }; 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( DA9E302C0EFC010300DFACC7 /* QuartzCore.framework */, DA9E302D0EFC010300DFACC7 /* OpenGLES.framework */, DA90DD490EFADE15001BABB5 /* AudioToolbox.framework */, 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, 1D30AB110D05D00D00671497 /* Foundation.framework */, ); name = Frameworks; sourceTree = ""; }; DA12F2FB0EF6E6B100A40C6D /* graphics */ = { isa = PBXGroup; children = ( DA8276E50EF9B2290061079D /* arrows.tga */, DA12F3E50EF6F00600A40C6D /* music.tga */, DA12F2FC0EF6E70100A40C6D /* title.tga */, DA12F2FD0EF6E70100A40C6D /* heart.tga */, DA12F2FE0EF6E70100A40C6D /* numerals.tga */, DA12F2FF0EF6E70100A40C6D /* spouseSprite.tga */, DA12F3000EF6E70100A40C6D /* tileSet.tga */, DA12F3010EF6E70100A40C6D /* chestPrize.tga */, DA12F3020EF6E70100A40C6D /* chestDust.tga */, DA12F3030EF6E70100A40C6D /* chest.tga */, DA12F3040EF6E70100A40C6D /* characterSpriteSad.tga */, DA12F3050EF6E70100A40C6D /* characterSprite.tga */, ); name = graphics; sourceTree = ""; }; DA12F31D0EF6E83D00A40C6D /* Customized */ = { isa = PBXGroup; children = ( DA12F33E0EF6E8BD00A40C6D /* blowUp.cpp */, DA90DD050EFAB907001BABB5 /* musicPlayer.cpp */, DA12F33F0EF6E8BD00A40C6D /* blowUp.h */, DA12F3400EF6E8BD00A40C6D /* common.cpp */, DA12F3410EF6E8BD00A40C6D /* game.cpp */, ); name = Customized; sourceTree = ""; }; DA12F31E0EF6E84900A40C6D /* Unchanged */ = { isa = PBXGroup; children = ( DA8C9E030EF80930002FCA67 /* minorGems */, DA90DD110EFAC2AF001BABB5 /* Timbre.cpp */, DA90DD120EFAC2AF001BABB5 /* Timbre.h */, DA90DD130EFAC2AF001BABB5 /* musicPlayer.h */, DA12F3CF0EF6EED000A40C6D /* common.h */, DA12F32D0EF6E89F00A40C6D /* World.h */, DA12F32E0EF6E89F00A40C6D /* World.cpp */, DA12F32F0EF6E89F00A40C6D /* score.h */, DA12F3300EF6E89F00A40C6D /* score.cpp */, DA12F3310EF6E89F00A40C6D /* map.h */, DA12F3320EF6E89F00A40C6D /* map.cpp */, DA12F3330EF6E89F00A40C6D /* landscape.h */, DA12F3340EF6E89F00A40C6D /* landscape.cpp */, DA12F3350EF6E89F00A40C6D /* HashTable.h */, DA12F3360EF6E89F00A40C6D /* Envelope.h */, DA12F3370EF6E89F00A40C6D /* Envelope.cpp */, ); name = Unchanged; sourceTree = ""; }; DA8C9E030EF80930002FCA67 /* minorGems */ = { isa = PBXGroup; children = ( DA8C9F050EF817F7002FCA67 /* StringBufferOutputStream.cpp */, DA8C9F060EF817F7002FCA67 /* StringBufferOutputStream.h */, DA8C9F070EF817F7002FCA67 /* stringUtils.cpp */, DA8C9F080EF817F7002FCA67 /* stringUtils.h */, DA8C9E1F0EF80985002FCA67 /* PathLinux.cpp */, DA8C9E1B0EF8095C002FCA67 /* TimeUnix.cpp */, DA8C9E1D0EF80968002FCA67 /* ThreadLinux.cpp */, ); name = minorGems; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 1D6058900D05DD3D006BFB54 /* Passage */ = { isa = PBXNativeTarget; buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "Passage" */; buildPhases = ( 1D60588D0D05DD3D006BFB54 /* Resources */, 1D60588E0D05DD3D006BFB54 /* Sources */, 1D60588F0D05DD3D006BFB54 /* Frameworks */, DA12F31C0EF6E79F00A40C6D /* ShellScript */, ); buildRules = ( ); dependencies = ( ); name = Passage; productName = testWindowApp; productReference = 1D6058910D05DD3D006BFB54 /* Passage.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "gameWindowApp" */; compatibilityVersion = "Xcode 3.1"; hasScannedForEncodings = 1; mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; projectDirPath = ""; projectRoot = ""; targets = ( 1D6058900D05DD3D006BFB54 /* Passage */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 1D60588D0D05DD3D006BFB54 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( DA86AEC90EF53C7100054E6B /* MainWindow.xib in Resources */, DA12F3060EF6E70100A40C6D /* title.tga in Resources */, DA12F3070EF6E70100A40C6D /* heart.tga in Resources */, DA12F3080EF6E70100A40C6D /* numerals.tga in Resources */, DA12F3090EF6E70100A40C6D /* spouseSprite.tga in Resources */, DA12F30A0EF6E70100A40C6D /* tileSet.tga in Resources */, DA12F30B0EF6E70100A40C6D /* chestPrize.tga in Resources */, DA12F30C0EF6E70100A40C6D /* chestDust.tga in Resources */, DA12F30D0EF6E70100A40C6D /* chest.tga in Resources */, DA12F30E0EF6E70100A40C6D /* characterSpriteSad.tga in Resources */, DA12F30F0EF6E70100A40C6D /* characterSprite.tga in Resources */, DA12F3E60EF6F00600A40C6D /* music.tga in Resources */, DA8276E60EF9B2290061079D /* arrows.tga in Resources */, DA8277840EF9FFE80061079D /* Icon.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ DA12F31C0EF6E79F00A40C6D /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = ""; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 1D60588E0D05DD3D006BFB54 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 1D60589B0D05DD56006BFB54 /* main.m in Sources */, DA7F11810EF6D77000CB6D50 /* gameWindowAppDelegate.mm in Sources */, DA12F3390EF6E89F00A40C6D /* World.cpp in Sources */, DA12F33A0EF6E89F00A40C6D /* score.cpp in Sources */, DA12F33B0EF6E89F00A40C6D /* map.cpp in Sources */, DA12F33C0EF6E89F00A40C6D /* landscape.cpp in Sources */, DA12F33D0EF6E89F00A40C6D /* Envelope.cpp in Sources */, DA12F3420EF6E8BD00A40C6D /* blowUp.cpp in Sources */, DA12F3430EF6E8BD00A40C6D /* common.cpp in Sources */, DA12F3440EF6E8BD00A40C6D /* game.cpp in Sources */, DA8C9E1C0EF8095C002FCA67 /* TimeUnix.cpp in Sources */, DA8C9E1E0EF80968002FCA67 /* ThreadLinux.cpp in Sources */, DA8C9E200EF80985002FCA67 /* PathLinux.cpp in Sources */, DA8C9F090EF817F7002FCA67 /* StringBufferOutputStream.cpp in Sources */, DA8C9F0A0EF817F7002FCA67 /* stringUtils.cpp in Sources */, DA90DD060EFAB907001BABB5 /* musicPlayer.cpp in Sources */, DA90DD140EFAC2AF001BABB5 /* Timbre.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 1D6058940D05DD3E006BFB54 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = gameWindowApp_Prefix.pch; HEADER_SEARCH_PATHS = /Users/jasonrohrer/cpp; INFOPLIST_FILE = Info.plist; PRODUCT_NAME = Passage; }; name = Debug; }; 1D6058950D05DD3E006BFB54 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = gameWindowApp_Prefix.pch; HEADER_SEARCH_PATHS = /Users/jasonrohrer/cpp; INFOPLIST_FILE = Info.plist; PRODUCT_NAME = Passage; }; name = Release; }; C01FCF4F08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; GCC_C_LANGUAGE_STANDARD = c99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; SDKROOT = iphoneos2.2; }; name = Debug; }; C01FCF5008A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; GCC_C_LANGUAGE_STANDARD = c99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; PREBINDING = NO; SDKROOT = iphoneos2.2; }; name = Release; }; DA9E30CB0EFC240700DFACC7 /* Distribution */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; GCC_C_LANGUAGE_STANDARD = c99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; PREBINDING = NO; SDKROOT = iphoneos2.2; }; name = Distribution; }; DA9E30CC0EFC240700DFACC7 /* Distribution */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Jason Rohrer"; COPY_PHASE_STRIP = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = gameWindowApp_Prefix.pch; HEADER_SEARCH_PATHS = /Users/jasonrohrer/cpp; INFOPLIST_FILE = Info.plist; PRODUCT_NAME = Passage; "PROVISIONING_PROFILE[sdk=iphoneos*]" = "0BE1AB5F-422D-4C27-A26D-B23A5A1F89C1"; }; name = Distribution; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "Passage" */ = { isa = XCConfigurationList; buildConfigurations = ( 1D6058940D05DD3E006BFB54 /* Debug */, 1D6058950D05DD3E006BFB54 /* Release */, DA9E30CC0EFC240700DFACC7 /* Distribution */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; C01FCF4E08A954540054247B /* Build configuration list for PBXProject "gameWindowApp" */ = { isa = XCConfigurationList; buildConfigurations = ( C01FCF4F08A954540054247B /* Debug */, C01FCF5008A954540054247B /* Release */, DA9E30CB0EFC240700DFACC7 /* Distribution */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; } passage-4+dfsg1.orig/gamma256/gameSource/iPhone/gameWindowAppDelegate.mm0000640000175000017500000002537211122761664024633 0ustar pabspabs// // testWindowAppAppDelegate.m // testWindowApp // // Created by Jason Rohrer on 12/14/08. // Copyright __MyCompanyName__ 2008. All rights reserved. // #import "gameWindowAppDelegate.h" @implementation gameWindowAppDelegate @synthesize window; @synthesize view; - (void)applicationDidFinishLaunching:(UIApplication *)application { printf( "App finished launching\n" ); printf( "Calling start anim\n" ); [view startAnimation]; printf( "Done starting animation\n" ); // Override point for customization after application launch [window makeKeyAndVisible]; // Configure and start the accelerometer // off for now //[[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / 15)]; //[[UIAccelerometer sharedAccelerometer] setDelegate:self]; } // UIAccelerometerDelegate method, called when the device accelerates. - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration { //printf( "%d --- accel called w %f,%f\n", timeOfCall, acceleration.x, acceleration.y ); // low pass filter float filterFactor = 0.5; accelerationBuffer[0] = acceleration.x * filterFactor + (1-filterFactor) * accelerationBuffer[0]; accelerationBuffer[1] = acceleration.y * filterFactor + (1-filterFactor) * accelerationBuffer[1]; accelerationBuffer[2] = acceleration.z * filterFactor + (1-filterFactor) * accelerationBuffer[2]; setOrientation( asin( accelerationBuffer[0] ), asin( accelerationBuffer[1] ) ); } - (void)dealloc { [window release]; [view stopAnimation]; [view release]; [super dealloc]; } @end #include "drawIntoScreen.h" #import #import @implementation MyView @synthesize animationTimer; @synthesize context; // You must implement this method + (Class)layerClass { return [CAEAGLLayer class]; } //The GL view is stored in the nib file. When it's unarchived it's sent -initWithCoder: - (id)initWithCoder:(NSCoder*)coder { if ((self = [super initWithCoder:coder])) { // Get the layer CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer; eaglLayer.opaque = YES; eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil]; context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; if (!context || ![EAGLContext setCurrentContext:context]) { [self release]; return nil; } } return self; } NSTimeInterval countStartTime; int appFrameCount = 0; - (void)layoutSubviews { [EAGLContext setCurrentContext:context]; [self destroyFramebuffer]; [self createFramebuffer]; NSDate *then = [NSDate date]; countStartTime = [then timeIntervalSinceReferenceDate]; [self drawFrame]; } - (BOOL)createFramebuffer { glGenFramebuffersOES(1, &viewFramebuffer); glGenRenderbuffersOES(1, &viewRenderbuffer); glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer]; glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer); glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth); glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight); if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) { NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); return NO; } glGenTextures( 1, &textureID ); return YES; } - (void)destroyFramebuffer { glDeleteFramebuffersOES(1, &viewFramebuffer); viewFramebuffer = 0; glDeleteRenderbuffersOES(1, &viewRenderbuffer); viewRenderbuffer = 0; if(depthRenderbuffer) { glDeleteRenderbuffersOES(1, &depthRenderbuffer); depthRenderbuffer = 0; } glDeleteTextures( 1, &textureID ); } - (void)setAnimationTimer:(NSTimer *)newTimer { [animationTimer invalidate]; animationTimer = newTimer; } - (void)startAnimation { NSTimeInterval animationInterval = 1 / 15.0; self.animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(drawFrame) userInfo:nil repeats:YES]; bitmapW = 128; bitmapH = 128; int screenPixels = bitmapW * bitmapH; bitmapBytes = screenPixels* 4; screenBitmap = (Uint32 *) malloc( bitmapBytes ); /* // for old DrawImage version provider = CGDataProviderCreateWithData( NULL, screenBitmap, screenPixels * 4, NULL ); colorSpaceRef = CGColorSpaceCreateDeviceRGB(); imageRef = CGImageCreate( bitmapW, bitmapH, 8, 32, 4 * bitmapW, colorSpaceRef, kCGImageAlphaNoneSkipLast, provider, NULL, NO, kCGRenderingIntentDefault ); */ initScreenDrawer( screenBitmap, bitmapW, bitmapH ); } - (void)stopAnimation { printf( "Stop anim called\n" ); self.animationTimer = nil; free( screenBitmap ); freeScreenDrawer(); } - (void)drawFrame { // old DrawImage version //[self setNeedsDisplay]; const GLfloat squareVertices[] = { -1.6f, -1.6f, 1.6f, -1.6f, -1.6f, 1.6f, 1.6f, 1.6f, }; /* const GLubyte squareColors[] = { 255, 255, 0, 255, 0, 255, 255, 255, 255, 0, 0, 0, 255, 0, 255, 255, }; */ const GLfloat squareTextureCoords[] = { 0, 0, 1, 0, 0, 1, 1, 1 }; [EAGLContext setCurrentContext:context]; glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer); glViewport(0, 0, backingWidth, backingHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrthof(-1.0f, 1.0f, -1.5f, 1.5f, -1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); //glClearColor(0.5f, 0.5f, 0.5f, 1.0f); //glClear(GL_COLOR_BUFFER_BIT); glVertexPointer(2, GL_FLOAT, 0, squareVertices); glEnableClientState(GL_VERTEX_ARRAY); //glColorPointer(4, GL_UNSIGNED_BYTE, 0, squareColors); //glEnableClientState(GL_COLOR_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, squareTextureCoords); glEnableClientState(GL_TEXTURE_COORD_ARRAY); // set new texture data drawIntoScreen( screenBitmap, bitmapW, bitmapH ); int error; GLenum texFormat = GL_RGBA; glBindTexture( GL_TEXTURE_2D, textureID ); error = glGetError(); if( error != GL_NO_ERROR ) { // error printf( "Error binding to texture id %d, error = %d\n", (int)textureID, error ); } glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); glTexImage2D( GL_TEXTURE_2D, 0, texFormat, bitmapW, bitmapH, 0, texFormat, GL_UNSIGNED_BYTE, screenBitmap ); error = glGetError(); if( error != GL_NO_ERROR ) { // error printf( "Error setting texture data for id %d, error = %d\n", (int)textureID, error ); printf( "Perhaps texture image width or height is not a power of 2\n" "Width = %lu, Height = %lu\n", bitmapW, bitmapH ); } glEnable( GL_TEXTURE_2D ); glBindTexture( GL_TEXTURE_2D, textureID ); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); [context presentRenderbuffer:GL_RENDERBUFFER_OES]; appFrameCount++; // disable FPS tracking if( false && appFrameCount > 100 ) { NSDate *now = [NSDate date]; NSTimeInterval newStartTime = [now timeIntervalSinceReferenceDate]; NSTimeInterval elapsedTime = newStartTime - countStartTime; printf( "FPS: %f\n", appFrameCount / elapsedTime ); countStartTime = newStartTime; appFrameCount = 0; } } /* // old DrawImage version #include unsigned int appFrameCountStartTime = time( NULL ); int appFrameCount = 0; - (void)drawRect:(CGRect)rect { //printf( "Draw Rect called!\n" ); drawIntoScreen( screenBitmap, bitmapW, bitmapH ); CGContextRef context = UIGraphicsGetCurrentContext(); //CGContextRotateCTM ( context, M_PI / 2 ); //CGContextTranslateCTM ( context, 0, -bitmapH ); CGRect imageRect = CGRectMake ( 0, 0, bitmapW, bitmapH ); CGContextDrawImage(context, imageRect, imageRef ); appFrameCount++; if( appFrameCount > 100 ) { unsigned int newTime = time( NULL ); unsigned int timeDelta = newTime - appFrameCountStartTime; printf( "FPS = %f\n", (double)appFrameCount / (double)timeDelta ); appFrameCount = 0; appFrameCountStartTime = newTime; } } */ // Handles the start of a touch - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { CGRect bounds = [self bounds]; UITouch* touch = [[event touchesForView:self] anyObject]; //Convert touch point from UIView referential to OpenGL one (upside-down flip) CGPoint location = [touch locationInView:self]; location.y = bounds.size.height - location.y; touchStartPoint( location.x, location.y ); } // Handles touch motion - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { CGRect bounds = [self bounds]; UITouch* touch = [[event touchesForView:self] anyObject]; //Convert touch point from UIView referential to OpenGL one (upside-down flip) CGPoint location = [touch locationInView:self]; location.y = bounds.size.height - location.y; touchMovePoint( location.x, location.y ); } // Handles touch end - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { CGRect bounds = [self bounds]; UITouch* touch = [[event touchesForView:self] anyObject]; //Convert touch point from UIView referential to OpenGL one (upside-down flip) CGPoint location = [touch locationInView:self]; location.y = bounds.size.height - location.y; touchEndPoint( location.x, location.y ); } @end passage-4+dfsg1.orig/gamma256/gameSource/iPhone/arrows.tga0000640000175000017500000000676511122273622022112 0ustar pabspabsO$$I>$H>$m]7m]7|I|I[[ڻmںmڀںmڻm[[|I|Im]7m]7H>$I>$$$$$I>$H>$m]7m]7|I|I[[ڻmںmڀںmڻm[[|I|Im]7m]7H>$I>$$$$$I>$H>$m]7m]7|I|I[[ڻmںmڀںmڻm[[|I|Im]7m]7H>$I>$$$$$I>$H>$m]7m]7|I|I[[ڻmںmڀںmڻm[[|I|Im]7m]7H>$I>$$$$$I>$H>$m]7m]7|I|I[[ڻmںmڀںmڻm[[|I|Im]7m]7H>$I>$$$passage-4+dfsg1.orig/gamma256/gameSource/iPhone/Icon.png0000640000175000017500000000077211122344016021462 0ustar pabspabsPNG  IHDR99zIDATxWNA6@B0wA|ME X7ĐgP͟e?@u bz_jZ!ӹ6J.P1غ@ V|}pg[IENDB`passage-4+dfsg1.orig/gamma256/gameSource/iPhone/main.m0000640000175000017500000000176411122345215021172 0ustar pabspabs// // main.m // testWindowApp // // Created by Jason Rohrer on 12/14/08. // Copyright __MyCompanyName__ 2008. All rights reserved. // #import int main(int argc, char *argv[]) { //printf( "Arg 0 = %s\n", argv[0] ); // arg 0 is the path to the app executable char *appDirectoryPath = strdup( argv[ 0 ] ); //printf( "Mac: app path %s\n", appDirectoryPath ); char *bundleName = "Passage.app"; char *appNamePointer = strstr( appDirectoryPath, bundleName ); if( appNamePointer != NULL ) { // terminate full app path to get bundle directory appNamePointer[ strlen( bundleName ) ] = '\0'; printf( "Mac: changing working dir to %s\n", appDirectoryPath ); chdir( appDirectoryPath ); } free( appDirectoryPath ); NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; int retVal = UIApplicationMain(argc, argv, nil, nil); [pool release]; return retVal; } passage-4+dfsg1.orig/gamma256/gameSource/iPhone/MainWindow.xib0000640000175000017500000002264711121526563022661 0ustar pabspabs 528 9F33 677 949.34 352.00 YES YES com.apple.InterfaceBuilder.IBCocoaTouchPlugin YES YES YES YES IBFilesOwner IBFirstResponder 1316 YES 1298 {320, 480} 3 MQA 2 NO {320, 480} 1 MSAxIDEAA NO NO YES delegate 4 window 5 view 11 YES 0 YES 2 YES -1 RmlsZSdzIE93bmVyA 3 -2 10 YES YES -1.CustomClassName -2.CustomClassName 10.CustomClassName 10.IBPluginDependency 2.IBAttributePlaceholdersKey 2.IBEditorWindowLastContentRect 2.IBPluginDependency 3.CustomClassName 3.IBPluginDependency YES UIApplication UIResponder MyView com.apple.InterfaceBuilder.IBCocoaTouchPlugin YES YES YES {{411, 129}, {320, 480}} com.apple.InterfaceBuilder.IBCocoaTouchPlugin gameWindowAppDelegate com.apple.InterfaceBuilder.IBCocoaTouchPlugin YES YES YES YES YES YES 11 YES MyView UIView IBProjectSource gameWindowAppDelegate.h MyView UIView IBUserSource gameWindowAppDelegate NSObject YES YES view window YES MyView UIWindow 0 gameWindowApp.xcodeproj 3 passage-4+dfsg1.orig/gamma256/gameSource/iPhone/Info.plist0000640000175000017500000000165411124755664022055 0ustar pabspabs CFBundleDevelopmentRegion English CFBundleDisplayName ${PRODUCT_NAME} CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIconFile Icon.png CFBundleIdentifier net.sf.hcsoftware.${PRODUCT_NAME} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL CFBundleSignature ???? CFBundleVersion 3.1 LSRequiresIPhoneOS NSMainNibFile MainWindow UIStatusBarHidden passage-4+dfsg1.orig/gamma256/gameSource/iPhone/common.cpp0000640000175000017500000000103711121535221022052 0ustar pabspabs#include "common.h" #include "minorGems/graphics/converters/TGAImageConverter.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/FileInputStream.h" Image *readTGA( char *inFileName ) { return readTGA( "graphics", inFileName ); } Image *readTGA( char *inFolderName, char *inFileName ) { // ignore passed-in path (use bundle root) File tgaFile( NULL, inFileName ); FileInputStream tgaStream( &tgaFile ); TGAImageConverter converter; return converter.deformatImage( &tgaStream ); } passage-4+dfsg1.orig/gamma256/gameSource/iPhone/gameWindowAppDelegate.h0000640000175000017500000000304511122756742024443 0ustar pabspabs// // testWindowAppAppDelegate.h // testWindowApp // // Created by Jason Rohrer on 12/14/08. // Copyright __MyCompanyName__ 2008. All rights reserved. // #include "drawIntoScreen.h" #import #import #import #import @interface MyView : UIView { @private NSTimer *animationTimer; /* The pixel dimensions of the backbuffer */ GLint backingWidth; GLint backingHeight; EAGLContext *context; /* OpenGL names for the renderbuffer and framebuffers used to render to this view */ GLuint viewRenderbuffer, viewFramebuffer; /* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */ GLuint depthRenderbuffer; GLuint textureID; Uint32 *screenBitmap; int bitmapW; int bitmapH; int bitmapBytes; // for old DrawImage version // CGDataProviderRef provider; // CGColorSpaceRef colorSpaceRef; // CGImageRef imageRef; } @property NSTimer *animationTimer; @property (nonatomic, retain) EAGLContext *context; - (void)startAnimation; - (void)stopAnimation; - (void)drawFrame; - (BOOL) createFramebuffer; - (void) destroyFramebuffer; @end @interface gameWindowAppDelegate : NSObject { UIWindow *window; MyView *view; // used for low-pass filtering UIAccelerationValue accelerationBuffer[3]; } @property (nonatomic, retain) IBOutlet UIWindow *window; @property (nonatomic, retain) IBOutlet MyView *view; @end passage-4+dfsg1.orig/gamma256/gameSource/iPhone/testScreenDrawer.cpp0000640000175000017500000000060011121760321024042 0ustar pabspabs #include "drawIntoScreen.h" #include void drawIntoScreen( Uint32 *inScreenBuffer, int inWidth, int inHeight ) { // add dot at random spot int x = rand() % inWidth; int y = rand() % inHeight; int i = y * inWidth + x; inScreenBuffer[ i ] = 0xFFFFFFFF; } void initScreenDrawer( Uint32 *inScreenBuffer, int inWidth, int inHeight ) { } void freeScreenDrawer() { }passage-4+dfsg1.orig/gamma256/gameSource/heart.png0000640000175000017500000000041110710207737020453 0ustar pabspabsPNG  IHDRTX LIDATXK Dx+UE~t"jf,CZK81M3/-J-d60n. Ҥ1 Dc 2[ rnPZ>,A{p,)Ψa/όX@/jy]Lw$E18tk 2b޷wUIENDB`passage-4+dfsg1.orig/gamma256/gameSource/map.h0000640000175000017500000000136010711176714017575 0ustar pabspabs// checks if position is blocked by wall char isBlocked( int inX, int inY ); // checks if chest is present // assumes position is not blocked #define CHEST_NONE 0 #define CHEST_CLOSED 1 #define CHEST_OPEN 2 char isChest( int inX, int inY ); // 8-bit binary indicating which of six external chest gems are present #define CHEST_RED_GEM 0x01 #define CHEST_GREEN_GEM 0x02 #define CHEST_ORANGE_GEM 0x04 #define CHEST_BLUE_GEM 0x08 #define CHEST_YELLOW_GEM 0x10 #define CHEST_MAGENTA_GEM 0x20 // assumes a chest is present unsigned char getChestCode( int inX, int inY ); void getChestCenter( int inX, int inY, int *outCenterX, int *outCenterY ); void openChest( int inX, int inY ); // resets map to a fresh state void resetMap(); passage-4+dfsg1.orig/gamma256/gameSource/score.cpp0000640000175000017500000000452410706116101020457 0ustar pabspabs#include "score.h" #include "common.h" #include "minorGems/util/stringUtils.h" #include "minorGems/graphics/Image.h" Image *numeralImage; int numeralW = 3; int numeralH = 4; int imagePixelCount; double *numeralRed; double *numeralGreen; double *numeralBlue; Uint32 *numeralARGB; void initScore() { numeralImage = readTGA( "numerals.tga" ); imagePixelCount = numeralImage->getWidth() * numeralImage->getHeight(); numeralRed = new double[ imagePixelCount ]; numeralGreen = new double[ imagePixelCount ]; numeralBlue = new double[ imagePixelCount ]; numeralARGB = new Uint32[ imagePixelCount ]; for( int i=0; igetChannel(0)[ i ]; numeralGreen[i] = 255 * numeralImage->getChannel(1)[ i ]; numeralBlue[i] = 255 * numeralImage->getChannel(2)[ i ]; unsigned char r = (unsigned char)( numeralRed[ i ] ); unsigned char g = (unsigned char)( numeralGreen[ i ] ); unsigned char b = (unsigned char)( numeralBlue[ i ] ); numeralARGB[i] = r << 16 | g << 8 | b; } } int getScoreHeight() { return numeralH; } void drawScore( Uint32 *inImage, int inWidth, int inHeight, int inScore ) { char *scoreString = autoSprintf( "%d", inScore ); int numDigits = strlen( scoreString ); int xPosition = inWidth - numDigits * ( numeralW + 1 ); for( int i=0; iIENDB`passage-4+dfsg1.orig/gamma256/gameSource/common.cpp0000640000175000017500000000103111376314017020634 0ustar pabspabs#include "common.h" #include "minorGems/graphics/converters/TGAImageConverter.h" #include "minorGems/io/file/File.h" #include "minorGems/io/file/FileInputStream.h" 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 ); } passage-4+dfsg1.orig/gamma256/gameSource/tileTemplate.png0000640000175000017500000000031710705677635022022 0ustar pabspabsPNG  IHDRV ?IDATH @h: 9 2b-ԐM"` Rf[WY+AL{"`_tt9C#jCzp 2+۷u]`JG$ " read platformSelection if [ "$platformSelection" = "q" ] then exit fi # use ASCII comparison. if [[ "$platformSelection" > "3" ]] then platformSelection="" fi if [[ "$platformSelection" < "1" ]] then platformSelection="" fi done 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 gamma256/gameSource/configure for the $platformName platform. Do not edit manually." > Makefile.temp rm -f Makefile cat Makefile.temp $platformMakefile Makefile.all > Makefile rm Makefile.temp exit passage-4+dfsg1.orig/gamma256/gameSource/music/0000750000175000017500000000000011376537567020005 5ustar pabspabspassage-4+dfsg1.orig/gamma256/gameSource/music/music.tga0000640000175000017500000042526210716061762021620 0ustar pabspabs WfW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮fW̮mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@passage-4+dfsg1.orig/gamma256/gameSource/score.h0000640000175000017500000000035711121533201020120 0ustar pabspabs#include typedef uint32_t Uint32; void initScore(); int getScoreHeight(); // draws score in upper-right corner of image void drawScore( Uint32 *inImage, int inWidth, int inHeight, int inScore ); void destroyScore(); passage-4+dfsg1.orig/gamma256/gameSource/Envelope.cpp0000640000175000017500000000545710716324077021145 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 Non-NIB-Code & other changes: Max Horn Feel free to customize this file to suit your needs */ #import @interface SDLMain : NSObject @end passage-4+dfsg1.orig/gamma256/gameSource/mac/SDLMain.m0000640000175000017500000002572410716122113021013 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; } passage-4+dfsg1.orig/gamma256/gameSource/Envelope.h0000640000175000017500000000230410715141023020561 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; }; passage-4+dfsg1.orig/gamma256/gameSource/World.cpp0000640000175000017500000005664611376314017020461 0ustar pabspabs#include "World.h" #include "common.h" #include "map.h" #include "minorGems/graphics/Image.h" #include "minorGems/util/SimpleVector.h" class GraphicContainer { public: GraphicContainer( const char *inTGAFileName ) { Image *image = readTGA( inTGAFileName ); mW = image->getWidth(); mH = image->getHeight(); int imagePixelCount = mW * mH; mRed = new double[ imagePixelCount ]; mGreen = new double[ imagePixelCount ]; mBlue = new double[ imagePixelCount ]; for( int i=0; igetChannel(0)[ i ]; mGreen[i] = 255 * image->getChannel(1)[ i ]; mBlue[i] = 255 * image->getChannel(2)[ i ]; } delete image; } ~GraphicContainer() { delete [] mRed; delete [] mGreen; delete [] mBlue; } double *mRed; double *mGreen; double *mBlue; int mW; int mH; }; GraphicContainer *tileContainer; GraphicContainer *chestContainer; GraphicContainer *spriteContainer; GraphicContainer *spriteSadContainer; GraphicContainer *spouseContainer; GraphicContainer *prizeAnimationContainer; GraphicContainer *dustAnimationContainer; GraphicContainer *heartAnimationContainer; // dimensions of one tile. TileImage contains 13 tiles, stacked vertically, // with blank lines between tiles int tileW = 8; int tileH = 8; int tileImageW; int tileImageH; int numTileSets; // how wide the swath of a world is that uses a given tile set int tileSetWorldSpan = 200; // overlap during tile set transition int tileSetWorldOverlap = 50; // for testing int tileSetSkip = 0; int tileSetOrder[18] = { 0, 2, 10, 1, 8, 3, 5, 6, 4, 7, 13, 9, 15, 14, 16, 12, 11, 17 }; int mapTileSet( int inSetNumber ) { // stay in bounds of tileSetOrder inSetNumber = inSetNumber % 18; int mappedSetNumber = tileSetOrder[ inSetNumber ]; // stay in bounds of tile set collection return mappedSetNumber % numTileSets; } int chestW = 8; int chestH = 8; int numGems = 6; int gemLocations[6] = { 41, 42, 43, 44, 45, 46 }; //int gemLocations[4] = { 10, 11, 12, 13 }; double gemColors[6][3] = { { 255, 0, 0 }, { 0, 255, 0 }, { 255, 160, 0 }, { 0, 0, 255 }, { 255, 255, 0 }, { 255, 0, 255 } }; class Animation { public: Animation( int inX, int inY, int inFrameW, int inFrameH, char inAutoStep, char inRemoveAtEnd, GraphicContainer *inGraphics ) : mX( inX ), mY( inY ), mFrameW( inFrameW ), mFrameH( inFrameH ), mPageNumber( 0 ), mFrameNumber( 0 ), mAutoStep( inAutoStep ), mRemoveAtEnd( inRemoveAtEnd ), mGraphics( inGraphics ) { mImageW = mGraphics->mW; mNumFrames = ( mGraphics->mH - mFrameH ) / mFrameH + 1; mNumPages = ( mGraphics->mW - mFrameW ) / mFrameW + 1; } // default constructor so that we can build a vector // of Animations Animation() { } // replaces graphics of animation void swapGraphics( GraphicContainer *inNewGraphics ) { mGraphics = inNewGraphics; mImageW = mGraphics->mW; mNumFrames = ( mGraphics->mH - mFrameH ) / mFrameH + 1; mNumPages = ( mGraphics->mW - mFrameW ) / mFrameW + 1; if( mPageNumber >= mNumPages ) { mPageNumber = mNumPages - 1; } if( mFrameNumber >= mNumFrames ) { mFrameNumber = mNumFrames - 1; } } int mX, mY; int mFrameW, mFrameH; int mImageW; // can blend between pages double mPageNumber; int mNumPages; int mFrameNumber; int mNumFrames; char mAutoStep; char mRemoveAtEnd; GraphicContainer *mGraphics; }; SimpleVector animationList; // pointers into vectors are unsafe //Animation *spriteAnimation; //Animation *spouseAnimation; int spriteAnimationIndex; int spouseAnimationIndex; char playerDead = false; char spouseDead = false; char metSpouse = false; void resetSampleHashTable(); void initWorld() { resetMap(); resetSampleHashTable(); playerDead = false; spouseDead = false; metSpouse = false; animationList.deleteAll(); tileImageW = tileContainer->mW; tileImageH = tileContainer->mH; numTileSets = (tileImageW + 1) / (tileW + 1); Animation character( 0, 0, 8, 8, false, false, spriteContainer ); animationList.push_back( character ); // unsafe // get pointer to animation in vector //spriteAnimation = animationList.getElement( animationList.size() - 1 ); spriteAnimationIndex = animationList.size() - 1; Animation spouse( 100, 7, 8, 8, false, false, spouseContainer ); spouse.mFrameNumber = 7; animationList.push_back( spouse ); // unsafe! // get pointer to animation in vector //spouseAnimation = animationList.getElement( animationList.size() - 1 ); spouseAnimationIndex = animationList.size() - 1; } char isSpriteTransparent( GraphicContainer *inContainer, int inSpriteIndex ) { // take transparent color from corner return inContainer->mRed[ inSpriteIndex ] == inContainer->mRed[ 0 ] && inContainer->mGreen[ inSpriteIndex ] == inContainer->mGreen[ 0 ] && inContainer->mBlue[ inSpriteIndex ] == inContainer->mBlue[ 0 ]; } struct rgbColorStruct { double r; double g; double b; }; typedef struct rgbColorStruct rgbColor; // outTransient set to true if sample returned is part of a transient // world feature (character sprite, chest, etc.) rgbColor sampleFromWorldNoWeight( int inX, int inY, char *outTransient ); // same, but wrapped in a hash table to store non-transient results rgbColor sampleFromWorldNoWeightHash( int inX, int inY ); Uint32 sampleFromWorld( int inX, int inY, double inWeight ) { rgbColor c = sampleFromWorldNoWeightHash( inX, inY ); unsigned char r = (unsigned char)( inWeight * c.r ); unsigned char g = (unsigned char)( inWeight * c.g ); unsigned char b = (unsigned char)( inWeight * c.b ); return r << 16 | g << 8 | b; } char isSpritePresent( int inX, int inY ) { // look at animations for( int i=0; i= 0 && animX < animW && animY >= 0 && animY < animH ) { return true; } } return false; } #include "HashTable.h" HashTable worldSampleHashTable( 30000 ); void resetSampleHashTable() { worldSampleHashTable.clear(); } rgbColor sampleFromWorldNoWeightHash( int inX, int inY ) { char found; rgbColor sample = worldSampleHashTable.lookup( inX, inY, &found ); if( isSpritePresent( inX, inY ) ) { // don't consider cached result if a sprite is present found = false; } if( found ) { return sample; } // else not found // call real function to get result char transient; sample = sampleFromWorldNoWeight( inX, inY, &transient ); // insert, but only if not transient if( !transient ) { worldSampleHashTable.insert( inX, inY, sample ); } return sample; } rgbColor sampleFromWorldNoWeight( int inX, int inY, char *outTransient ) { *outTransient = false; rgbColor returnColor; char isSampleAnim = false; // consider sampling from an animation // draw them in reverse order so that oldest sprites are drawn on top for( int i=animationList.size() - 1; i>=0; i-- ) { Animation a = *( animationList.getElement( i ) ); int animW = a.mFrameW; int animH = a.mFrameH; // pixel position relative to animation center // player position centered on sprint left-to-right int animX = (int)( inX - a.mX + a.mFrameW / 2 ); int animY = (int)( inY - a.mY + a.mFrameH / 2 ); if( animX >= 0 && animX < animW && animY >= 0 && animY < animH ) { // pixel is in animation frame int animIndex = animY * a.mImageW + animX; // skip to appropriate anim page animIndex += (int)a.mPageNumber * (animW + 1); // skip to appropriate anim frame animIndex += a.mFrameNumber * a.mImageW * ( animH + 1 ); // page to blend with int animBlendIndex = animIndex + animW + 1; double blendWeight = a.mPageNumber - (int)a.mPageNumber; if( !isSpriteTransparent( a.mGraphics, animIndex ) ) { // in non-transparent part if( blendWeight != 0 ) { returnColor.r = ( 1 - blendWeight ) * a.mGraphics->mRed[ animIndex ] + blendWeight * a.mGraphics->mRed[ animBlendIndex ]; returnColor.g = ( 1 - blendWeight ) * a.mGraphics->mGreen[ animIndex ] + blendWeight * a.mGraphics->mGreen[ animBlendIndex ]; returnColor.b = ( 1 - blendWeight ) * a.mGraphics->mBlue[ animIndex ] + blendWeight * a.mGraphics->mBlue[ animBlendIndex ]; } else { // no blend returnColor.r = a.mGraphics->mRed[ animIndex ]; returnColor.g = a.mGraphics->mGreen[ animIndex ]; returnColor.b = a.mGraphics->mBlue[ animIndex ]; } *outTransient = true; // don't return here, because there might be other // animations and sprites that are on top of // this one isSampleAnim = true; } } } if( isSampleAnim ) { // we have already found an animation here that is on top // of whatever map graphics we might sample below // thus, we can return now return returnColor; } int tileIndex; char blocked = isBlocked( inX, inY ); if( !blocked ) { // empty tile tileIndex = 0; } else { int neighborsBlockedBinary = 0; if( isBlocked( inX, inY - tileH ) ) { // top neighborsBlockedBinary = neighborsBlockedBinary | 1; } if( isBlocked( inX + tileW, inY ) ) { // right neighborsBlockedBinary = neighborsBlockedBinary | 1 << 1; } if( isBlocked( inX, inY + tileH ) ) { // bottom neighborsBlockedBinary = neighborsBlockedBinary | 1 << 2; } if( isBlocked( inX - tileW, inY ) ) { // left neighborsBlockedBinary = neighborsBlockedBinary | 1 << 3; } // skip empty tile, treat as tile index neighborsBlockedBinary += 1; tileIndex = neighborsBlockedBinary; } // pick a tile set int netWorldSpan = tileSetWorldSpan + tileSetWorldOverlap; int tileSet = inX / netWorldSpan + tileSetSkip; int overhang = inX % netWorldSpan; if( inX < 0 ) { // fix to a constant tile set below 0 overhang = 0; tileSet = 0; } // is there blending with next tile set? int blendTileSet = tileSet + 1; double blendWeight = 0; if( overhang > tileSetWorldSpan ) { blendWeight = ( overhang - tileSetWorldSpan ) / (double) tileSetWorldOverlap; } // else 100% blend of our first tile set tileSet = tileSet % numTileSets; blendTileSet = blendTileSet % numTileSets; // make sure not negative if( tileSet < 0 ) { tileSet += numTileSets; } if( blendTileSet < 0 ) { blendTileSet += numTileSets; } // apply mapping tileSet = mapTileSet( tileSet ); blendTileSet = mapTileSet( blendTileSet ); // sample from tile image int imageY = inY % tileH; int imageX = inX % tileW; if( imageX < 0 ) { imageX += tileW; } if( imageY < 0 ) { imageY += tileH; } // offset to top left corner of tile int tileImageOffset = tileIndex * ( tileH + 1 ) * tileImageW + tileSet * (tileW + 1); int blendTileImageOffset = tileIndex * ( tileH + 1 ) * tileImageW + blendTileSet * (tileW + 1); int imageIndex = tileImageOffset + imageY * tileImageW + imageX; int blendImageIndex = blendTileImageOffset + imageY * tileImageW + imageX; returnColor.r = (1-blendWeight) * tileContainer->mRed[ imageIndex ] + blendWeight * tileContainer->mRed[ blendImageIndex ]; returnColor.g = (1-blendWeight) * tileContainer->mGreen[ imageIndex ] + blendWeight * tileContainer->mGreen[ blendImageIndex ]; returnColor.b = (1-blendWeight) * tileContainer->mBlue[ imageIndex ] + blendWeight * tileContainer->mBlue[ blendImageIndex ]; // only consider drawing chests in empty spots if( !blocked && isChest( inX, inY ) ) { // draw chest here char chestType = isChest( inX, inY ); // sample from chest image int imageY = inY % chestH; int imageX = inX % chestW; if( imageX < 0 ) { imageX += chestW; } if( imageY < 0 ) { imageY += chestH; } int spriteIndex = 0; if( chestType == CHEST_OPEN ) { spriteIndex = 1; } // skip to sub-sprite int spriteOffset = spriteIndex * chestW * ( chestH + 1 ); int subSpriteIndex = imageY * chestW + imageX; int imageIndex = spriteOffset + subSpriteIndex; if( !isSpriteTransparent( chestContainer, imageIndex ) ) { if( chestType == CHEST_CLOSED ) { *outTransient = true; } // check if this is one of the gem locations char isGem = false; int gemNumber = 0; for( int i=0; imRed[ imageIndex ]; returnColor.g = chestContainer->mGreen[ imageIndex ]; returnColor.b = chestContainer->mBlue[ imageIndex ]; } } } return returnColor; } int getTileWidth() { return tileW; } int getTileHeight() { return tileH; } void destroyWorld() { /* printf( "%d hits, %d misses, %f hit ratio\n", hitCount, missCount, hitCount / (double)( hitCount + missCount ) ); */ } void stepAnimations() { for( int i=0; imAutoStep ) { if( a->mFrameNumber < a->mNumFrames - 1 ) { a->mFrameNumber ++; } else if( a->mRemoveAtEnd ) { // remove it animationList.deleteElement( i ); // back up in list for next loop iteration i--; } } } } void startPrizeAnimation( int inX, int inY ) { Animation a( inX, inY, 16, 16, true, true, prizeAnimationContainer ); animationList.push_back( a ); } void startDustAnimation( int inX, int inY ) { Animation a( inX, inY, 16, 16, true, true, dustAnimationContainer ); animationList.push_back( a ); } void startHeartAnimation( int inX, int inY ) { Animation a( inX, inY, 16, 16, true, true, heartAnimationContainer ); animationList.push_back( a ); } #include void setPlayerPosition( int inX, int inY ) { Animation *spriteAnimation = animationList.getElement( spriteAnimationIndex ); char moving = false; if( inX != spriteAnimation->mX ) { moving = true; } spriteAnimation->mX = inX; // player position centered at sprite's feet int newSpriteY = inY - spriteAnimation->mFrameH / 2 + 1; if( newSpriteY != spriteAnimation->mY ) { moving = true; } spriteAnimation->mY = newSpriteY; if( metSpouse && ! spouseDead ) { Animation *spouseAnimation = animationList.getElement( spouseAnimationIndex ); // spouse stands immediately in front of player int desiredSpouseX = inX + spouseAnimation->mFrameH; int desiredSpouseY = spriteAnimation->mY; // gravitates there gradually one pixel at a time in each x and y int dX = desiredSpouseX - spouseAnimation->mX; int dY = desiredSpouseY - spouseAnimation->mY; // convert to -1, 0, or +1 if( dX != 0 ) { dX = (int)( dX / fabs( dX ) ); } if( dY != 0 ) { dY = (int)( dY / fabs( dY ) ); } if( moving ) { // only execute this transition when player is moving spouseAnimation->mX += dX; spouseAnimation->mY += dY; } // check for heart animation and have it track moving couple for( int i=0; imGraphics == heartAnimationContainer ) { // move it halfway between player and spouse a->mX = ( spouseAnimation->mX - spriteAnimation->mX ) / 2 + spriteAnimation->mX; a->mY = ( spouseAnimation->mY - spriteAnimation->mY ) / 2 + spriteAnimation->mY + 1; } } } } void setPlayerSpriteFrame( int inFrame ) { Animation *spriteAnimation = animationList.getElement( spriteAnimationIndex ); spriteAnimation->mFrameNumber = inFrame; if( metSpouse && ! spouseDead ) { Animation *spouseAnimation = animationList.getElement( spouseAnimationIndex ); // spouse follows player spouseAnimation->mFrameNumber = inFrame; } } void setCharacterAges( double inAge ) { Animation *spriteAnimation = animationList.getElement( spriteAnimationIndex ); Animation *spouseAnimation = animationList.getElement( spouseAnimationIndex ); // 0 -> 0.25, constant page 0 if( inAge <= 0.25 ) { spriteAnimation->mPageNumber = 0; spouseAnimation->mPageNumber = 0; } // 0.75 - 1.0, constant last page else if( inAge >= 0.75 ) { spriteAnimation->mPageNumber = spriteAnimation->mNumPages - 1; spouseAnimation->mPageNumber = spouseAnimation->mNumPages - 1; } else { // blend of pages in between double blendingAge = ( inAge - 0.25 ) / 0.5; spriteAnimation->mPageNumber = blendingAge * ( spriteAnimation->mNumPages - 1 ); spouseAnimation->mPageNumber = blendingAge * ( spouseAnimation->mNumPages - 1 ); } } void getSpousePosition( int *outX, int *outY ) { Animation *spouseAnimation = animationList.getElement( spouseAnimationIndex ); *outX = spouseAnimation->mX; *outY = spouseAnimation->mY + spouseAnimation->mFrameH / 2 - 1; } char haveMetSpouse() { return metSpouse && ! spouseDead; } void meetSpouse() { metSpouse = true; } void diePlayer() { Animation *spriteAnimation = animationList.getElement( spriteAnimationIndex ); playerDead = true; // tombstone spriteAnimation->mFrameNumber = 8; } void dieSpouse() { Animation *spriteAnimation = animationList.getElement( spriteAnimationIndex ); Animation *spouseAnimation = animationList.getElement( spouseAnimationIndex ); spouseDead = true; // tombstone spouseAnimation->mFrameNumber = 8; if( metSpouse ) { // swap player sprite with sad sprite spriteAnimation->swapGraphics( spriteSadContainer ); } } char isPlayerDead() { return playerDead; } char isSpouseDead() { return spouseDead; } void loadWorldGraphics() { tileContainer = new GraphicContainer( "tileSet.tga" ); chestContainer = new GraphicContainer( "chest.tga" ); spriteContainer = new GraphicContainer( "characterSprite.tga" ); spriteSadContainer = new GraphicContainer( "characterSpriteSad.tga" ); spouseContainer = new GraphicContainer( "spouseSprite.tga" ); prizeAnimationContainer = new GraphicContainer( "chestPrize.tga" ); dustAnimationContainer = new GraphicContainer( "chestDust.tga" ); heartAnimationContainer = new GraphicContainer( "heart.tga" ); } void destroyWorldGraphics() { delete tileContainer; delete chestContainer; delete spriteContainer; delete spriteSadContainer; delete spouseContainer; delete prizeAnimationContainer; delete dustAnimationContainer; delete heartAnimationContainer; } passage-4+dfsg1.orig/gamma256/gameSource/Makefile.MinGW0000640000175000017500000000035310716362527021274 0ustar pabspabsPLATFORM_PATH = win32 PLATFORM_NAME = Win32 TIME_PLATFORM_PATH = win32 TIME_PLATFORM_NAME = Win32 PLATFORM_COMPILE_FLAGS = # -mwindows hides the command window on app launch PLATFORM_LINK_FLAGS = -lmingw32 -lSDLmain -lSDL -mwindows passage-4+dfsg1.orig/gamma256/gameSource/Timbre.cpp0000640000175000017500000000770610716063732020607 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; sZE8HXMѲqwaWlh>aܹ g~}*q@:Q|'<}{zUP;(ǧIENDB`passage-4+dfsg1.orig/gamma256/build/win32/Passage.ico0000640000175000017500000000137610716100031020664 0ustar pabspabs ( @44mmmIIIII$$$""wwww""""wwww""""wwww""""wwww""DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD33UUUU3333UUUU3333UUUU3333UUUU33UUUUUUUUUUUUUUUUffff3333ffff3333ffff3333ffff3333ffff33ffff33ffff33ffff33ffffffffffffffffffffffffpassage-4+dfsg1.orig/gamma256/build/macOSX/0000750000175000017500000000000011376537560017015 5ustar pabspabspassage-4+dfsg1.orig/gamma256/build/macOSX/Passage.app/0000750000175000017500000000000011376537560021157 5ustar pabspabspassage-4+dfsg1.orig/gamma256/build/macOSX/Passage.app/Contents/0000750000175000017500000000000011376537560022754 5ustar pabspabspassage-4+dfsg1.orig/gamma256/build/macOSX/Passage.app/Contents/PkgInfo0000640000175000017500000000001010716073112024205 0ustar pabspabsAPPL????passage-4+dfsg1.orig/gamma256/build/macOSX/Passage.app/Contents/Info.plist0000640000175000017500000000177210716156356024731 0ustar pabspabs CFBundleInfoDictionaryVersion 6.0 CFBundleIdentifier org.passage CFBundleDevelopmentRegion English CFBundleExecutable Passage CFBundleIconFile Passage.icns CFBundleName Passage CFBundlePackageType APPL CFBundleSignature ???? CFBundleVersion 0 CFBundleShortVersionString 0 CFBundleGetInfoString Passage CFBundleLongVersionString 0 NSHumanReadableCopyright Public Domain, 2007 LSRequiresCarbon CSResourcesFileMapped passage-4+dfsg1.orig/gamma256/build/macOSX/Passage.app/Contents/Resources/0000750000175000017500000000000011376537560024726 5ustar pabspabspassage-4+dfsg1.orig/gamma256/build/macOSX/Passage.app/Contents/Resources/Passage.rsrc0000640000175000017500000000552710716073113027200 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-D01#b""#b10?????DDp @@D!@@@@!p8??|>D88< ngca`pv0<@?<<~ocpp~<<@DPPP???????? D@@1G@@???D`D@x`qy|~|0l0F00xxxD>~>6b`?D????D? ?? Dp8?!1:|<<>?? Dxpp`HH88xp>\<<8|D @ *8`>|p?? AK??_?Ox???x><`A`@ 00` ? o޽fo޻effo;fffn,ffff`¦ffffнfffmffff\fffm ffP] m u m eo+V^^]33^^3333_Ҁ^]]ҀҀ++Ҁ+WҀV~W+V1͆+VzV*+[ STR#RMENU^MBARjcarbvldesCURSICN#Nics#Zics4fics8r?ems   / wO'oGSimple Alert Messagespassage-4+dfsg1.orig/gamma256/build/macOSX/Passage.app/Contents/Resources/Passage.icns0000640000175000017500000004504210716341140027155 0ustar pabspabsicnsJ"it32 YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYtYtYtYtYtYtYtYtYtYtYtYtYtYtYtYtYtYtYtYtYtYtYtYtYtYtYtYtYtYtYtYtY6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6$6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYoYoYoYoYoYoYoYoYoYoYoYoYoYoYoYoY6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Y6Yt8mk@passage-4+dfsg1.orig/gamma256/build/macOSX/Passage.app/Contents/MacOS/0000750000175000017500000000000011376537560023716 5ustar pabspabspassage-4+dfsg1.orig/gamma256/build/macOSX/Passage.app/Contents/MacOS/dummy.txt0000640000175000017500000000012510716073113025573 0ustar pabspabsA placeholder file so that "cvs export" will include this otherwise empty directory.passage-4+dfsg1.orig/gamma256/build/macOSX/iconColor.png0000640000175000017500000000062210716340355021442 0ustar pabspabsPNG  IHDRL\YIDATxݱ0a:0a,ac- xﯹ3]R3 CO].KWs<@ 1saX@zo o x k唻_ @@?/h:_}gn   Dӧ;g3%(6R` @ `{±Lc RK@ )GIENDB`passage-4+dfsg1.orig/gamma256/build/macOSX/iconMask.png0000640000175000017500000000047710716340355021267 0ustar pabspabsPNG  IHDRL\IDATxA Aj Dt cSxfߟ @>n  @ ,n^nk @hA   P K@ ?#,A@ ~1,A@-+$a?wIENDB`passage-4+dfsg1.orig/gamma256/prototypes/0000750000175000017500000000000011376537567017023 5ustar pabspabspassage-4+dfsg1.orig/gamma256/prototypes/screenCompress/0000750000175000017500000000000011376537567022016 5ustar pabspabspassage-4+dfsg1.orig/gamma256/prototypes/screenCompress/mapTile.tga0000640000175000017500000000035410676274526024104 0ustar pabspabsʇʑʇʇʇʑʇʇʇʑʇʇʑʑʑʑʑʑʇʑʇʇʇʑʇʇʇʑʇʇʑʑʑʑʑʑTRUEVISION-XFILE.passage-4+dfsg1.orig/gamma256/prototypes/screenCompress/characterSprite.png0000640000175000017500000000046710702733433025635 0ustar pabspabsPNG  IHDRGceIDAT8͔q E"T :g3NŲ/\R2@u., < ~AsfAQ*w>Zع:Ҩjgr8&"qt`l-]Ճ85j]] yB4\w agE9 zp!:x|!!UNεCf 0oE3OADx}`FF v_R'ǝNIENDB`passage-4+dfsg1.orig/gamma256/prototypes/screenCompress/tileSet.png0000640000175000017500000000147710700476014024122 0ustar pabspabsPNG  IHDRIDATXY0 \h?5pT{y&{ E0g8zhd[H,wiQy\GVz=O=]ӯS^-[T?[*ڻS7OKTTӿgIENDB`passage-4+dfsg1.orig/gamma256/prototypes/screenCompress/sdlTest.cpp0000640000175000017500000000464110676755435024150 0ustar pabspabs// FIXME: // why does this end up with a blank, white screen after 5 seconds // while the demo code (testsprite) works fine? // Does it only happen on win32 #include #include #include // for memcpy #include #include #include void catch_int(int sig_num) { printf( "Quiting...\n" ); //currentStep = numSteps; exit( 0 ); signal( SIGINT, catch_int ); } // if SDL.h is included before our main function, the linker complains // about missing WinMain // This fixes it int mainFunction(); int main() { mainFunction(); } #include int mainFunction() { // let catch_int handle interrupt (^c) signal( SIGINT, catch_int ); int w = 640; int h = 480; if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE ) < 0 ) { printf( "Couldn't initialize SDL: %s\n", SDL_GetError() ); return -1; } SDL_Surface *screen = SDL_SetVideoMode( w, h, 32, SDL_SWSURFACE ); if ( screen == NULL ) { printf( "Couldn't set %dx%dx32 video mode: %s\n", w, h, SDL_GetError() ); return-1; } Uint32 *buffer = (Uint32 *)( screen->pixels ); char white = false; char done = false; while( !done ) { if( white ) { SDL_FillRect(screen, NULL, 0x00FFFFFF); } else { SDL_FillRect(screen, NULL, 0x00000000); } /* for( int y=0; y #include #include "minorGems/util/SimpleVector.h" double landscape( double inX, double inY, double inT, double inBaseFrequency, double inRoughness, int inDetail ) { if( inDetail < 0 ) { return 0.0; } else { // frequency of octave double frequency = inBaseFrequency * pow( 2, inDetail ); double amplitude = pow( inRoughness, inDetail ); return amplitude * noise4d( inX * frequency, inY * frequency, // index different planes of noise inDetail, inT ) + landscape( inX, inY, inT, inBaseFrequency, inRoughness, inDetail - 1 ); } } double variableRoughnessLandscape( double inX, double inY, double inT, double inBaseFrequency, double inRoughnessChangeFrequency, double inMinRoughness, double inMaxRoughness, int inDetail ) { double roughnessFreqX = inX * inRoughnessChangeFrequency; double roughnessFreqY = inY * inRoughnessChangeFrequency; // use low-frequency noise 4d to select landscape roughness // between 0 and 1 double roughness = ( noise4d( 6, roughnessFreqX, roughnessFreqY, inT ) + 1 ) / 2; // move roughness into specified range roughness = roughness * ( inMaxRoughness - inMinRoughness ) + inMinRoughness; return landscape( inX, inY, inT, inBaseFrequency, roughness, inDetail ); } int getRandomPoints( double inStartX, double inEndX, double inStartY, double inEndY, double inT, double inSampleStepSize, double inDensity, double **outXCoordinates, double **outYCoordinates ) { SimpleVector *xCoordinates = new SimpleVector(); SimpleVector *yCoordinates = new SimpleVector(); // discretize startX and start Y so that sample grid for differently-placed // windows always meshes // use ceil to ensure that starting points are always inside the // inStart/inEnd bounds double discretizedStartX = inSampleStepSize * ceil( inStartX / inSampleStepSize ); double discretizedStartY = inSampleStepSize * ceil( inStartY / inSampleStepSize ); // put a point wherever we have a zero-crossing double lastSample = 1; for( double x=discretizedStartX; x<=inEndX; x+=inSampleStepSize ) { for( double y=discretizedStartY; y<=inEndY; y+=inSampleStepSize ) { double landscapeSample = variableRoughnessLandscape( 30 * x + 1000, 30 * y + 1000, inT + 1000, 0.01, 0.001, 0.25, 0.65, 0 ); // shift landscape up to reduce chance of zero-crossing landscapeSample = (1-inDensity) * 0.5 + 0.5 + landscapeSample ; if( landscapeSample < 0 && lastSample >= 0 || landscapeSample >= 0 && landscapeSample < 0 ) { // sign change // hit xCoordinates->push_back( x ); yCoordinates->push_back( y ); } lastSample = landscapeSample; } } *outXCoordinates = xCoordinates->getElementArray(); *outYCoordinates = yCoordinates->getElementArray(); int numPoints = xCoordinates->size(); delete xCoordinates; delete yCoordinates; return numPoints; } /** * Computes a 32-bit random number. * Use linear congruential method. * * @param inSeed the seed to use. */ // this is the readable version of the funcion // it has been turned into a set of macros below inline unsigned long random32_readable( unsigned long inSeed ) { // this is the true hot-spot of the entire landscape function // thus, optimization is warranted. // multiplier = 3141592621 // use hex to avoid warnings //unsigned long multiplier = 0xBB40E62D; //unsigned long increment = 1; // better: // unsigned long multiplier = 196314165 // unsigned long increment = 907633515 // this will automatically be mod-ed by 2^32 because of the limit // of the unsigned long type // return multiplier * inSeed + increment; //return 0xBB40E62D * inSeed + 1; //return 196314165 * inSeed + 907633515; //int n = ( inSeed << 13 ) ^ inSeed; //return n * (n * n * 15731 + 789221) + 1376312589; //const unsigned long Num1 = (inSeed * 0xFEA09B9DLU) + 1; //const unsigned long Num2 = ((inSeed * 0xB89C8895LU) + 1) >> 16; //return Num1 ^ Num2; /* unsigned int rseed=(inSeed*15064013)^(inSeed*99991+604322121)^(inSeed*45120321)^(inSeed*5034121+13); const unsigned long Num1 = (inSeed * 0xFEA09B9DLU) + 1; const unsigned long Num2 = ((inSeed * 0xB89C8895LU) + 1) >> 16; rseed *= Num1 ^ Num2; return rseed; */ const unsigned long Num1 = (inSeed * 0xFEA09B9DLU) + 1; const unsigned long Num2 = ((inSeed^Num1) * 0x9C129511LU) + 1; const unsigned long Num3 = (inSeed * 0x2512CFB8LU) + 1; const unsigned long Num4 = ((inSeed^Num3) * 0xB89C8895LU) + 1; const unsigned long Num5 = (inSeed * 0x6BF962C1LU) + 1; const unsigned long Num6 = ((inSeed^Num5) * 0x4BF962C1LU) + 1; return Num2 ^ (Num4 >> 11) ^ (Num6 >> 22); } // faster as a set of macros #define Num1( inSeed ) \ ( ( inSeed * 0xFEA09B9DLU ) + 1 ) #define Num2( inSeed ) \ ( ( ( inSeed ^ Num1( inSeed ) ) * 0x9C129511LU ) + 1 ) #define Num3( inSeed ) \ ( ( inSeed * 0x2512CFB8LU ) + 1 ) #define Num4( inSeed ) \ ( ( ( inSeed ^ Num3( inSeed ) ) * 0xB89C8895LU ) + 1 ) #define Num5( inSeed ) \ ( ( inSeed * 0x6BF962C1LU ) + 1 ) #define Num6( inSeed ) \ ( ( ( inSeed ^ Num5( inSeed ) ) * 0x4BF962C1LU ) + 1 ) #define random32( inSeed ) \ ( Num2( inSeed ) ^ (Num4( inSeed ) >> 11) ^ (Num6( inSeed ) >> 22) ) #define invMaxIntAsDouble 2.32830643708e-10 // 1/(x/2) = 2*(1/x) //double invHalfMaxIntAsDouble = 2 * invMaxIntAsDouble; // 2.32830643708e-10 //+ 2.32830643708e-10 //------------------- // 4.65661287416e-10 #define invHalfMaxIntAsDouble 4.65661287416e-10 #define mixFour( x, y, z, t ) ( x ^ (y * 57) ^ (z * 131) ^ (t * 2383) ) /** * Maps 4d integer coordinates into a [-1..1] noise space. * * @param x, y, z, t the 4d coordinates. * * @return a random value in the range [-1..1] */ // keep readable version around for reference // it has been replaced by a macro below inline double noise4dInt32_readable( unsigned long x, unsigned long y, unsigned long z, unsigned long t ) { //double maxIntAsDouble = 4294967295.0; // modular addition automatic // multiply x, y, z, and t by distinct primes to // avoid correllations. // using xor ( ^ ) here seems to avoid correllations that show // up when using addition. // mix x, y, z, and t unsigned long randomSeed = x ^ y * 57 ^ z * 131 ^ t * 2383; // a random value between 0 and max unsigned long unsigned long randomValue = random32( randomSeed ); // a random value between 0 and 2 double zeroTwoValue = randomValue * invHalfMaxIntAsDouble; // a random value between -1 and 1 return zeroTwoValue - 1; } // noise4dInt32 function call itself was the slowest spot in code // (found with profiler) // turn into a set of macros // matches original parameter format #define noise4dInt32( x, y, z, t ) \ random32( mixFour( x, y, z, t ) ) \ * invHalfMaxIntAsDouble - 1 // problem: now that random32 is a macro, we are passing the unevaluated // expression, ( x ^ (y * 57) ^ (z * 131) ^ (t * 2383) ), down into it. // it is being evaluated 6 times within the depths of the random32 macro // thus, we need to provide a new format where the caller can precompute // the mix for us. This is even faster. #define noise1dInt32( precomputedMix ) \ random32( precomputedMix ) \ * invHalfMaxIntAsDouble - 1 /* * The following functions (blendNoiseNd) do 4d linear interpolation * one dimension at a time. * * The end result is 8 calls to blendNoise1d (and 16 calls to noise4dInt32). * * This method was inspired by the functional implementations---I am * decomposing a complicated problem into sub-problems that are easier * to solve. */ // faster than f * b + (1-f) * a // one less multiply #define linearInterpolation( t, a, b ) ( a + t * ( b - a ) ) /** * Blends 4d discrete (integer-parameter) noise function along one dimension * with 3 fixed integer parameters. */ inline double blendNoise1d( double x, unsigned long y, unsigned long z, unsigned long t ) { double floorX = floor( x ); unsigned long floorIntX = (unsigned long)floorX; if( floorX == x ) { unsigned long precomputedMix = mixFour( floorIntX, y, z, t ); return noise1dInt32( precomputedMix ); } else { unsigned long ceilIntX = floorIntX + 1; // cosine interpolation // from http://freespace.virgin.net/hugo.elias/models/m_perlin.htm double ft = ( x - floorX ) * M_PI; double f = ( 1 - cos( ft ) ) * .5; // need to pre-store intermediate values because noise4dInt32 is a // macro // thus, we end up calling the noise1dInt32 function instead unsigned long precomputedMix = mixFour( floorIntX, y, z, t ); double valueAtFloor = noise1dInt32( precomputedMix ); precomputedMix = mixFour( ceilIntX, y, z, t ); double valueAtCeiling = noise1dInt32( precomputedMix ); return linearInterpolation( f, valueAtFloor, valueAtCeiling ); } } /** * Blends 4d discrete (integer-parameter) noise function along 2 dimensions * with 2 fixed integer parameters. */ double blendNoise2d( double x, double y, unsigned long z, unsigned long t ) { double floorY = floor( y ); unsigned long floorIntY = (unsigned long)floorY; if( floorY == y ) { return blendNoise1d( x, floorIntY, z, t ); } else { unsigned long ceilIntY = floorIntY + 1; // cosine interpolation // from http://freespace.virgin.net/hugo.elias/models/m_perlin.htm double ft = ( y - floorY ) * M_PI; double f = ( 1 - cos( ft ) ) * .5; return ( f ) * blendNoise1d( x, ceilIntY, z, t ) + ( 1 - f ) * blendNoise1d( x, floorIntY, z, t ); } } /** * Blends 4d discrete (integer-parameter) noise function along 3 dimensions * with 1 fixed integer parameters. */ double blendNoise3d( double x, double y, double z, unsigned long t ) { double floorZ = floor( z ); unsigned long floorIntZ = (unsigned long)floorZ; if( floorZ == z ) { return blendNoise2d( x, y, floorIntZ, t ); } else { unsigned long ceilIntZ = floorIntZ + 1; // cosine interpolation // from http://freespace.virgin.net/hugo.elias/models/m_perlin.htm double ft = ( z - floorZ ) * M_PI; double f = ( 1 - cos( ft ) ) * .5; return ( f ) * blendNoise2d( x, y, ceilIntZ, t ) + ( 1 - f ) * blendNoise2d( x, y, floorIntZ, t ); } } /** * Blends 4d discrete (integer-parameter) noise function along 4 dimensions. */ double noise4d( double x, double y, double z, double t ) { double floorT = floor( t ); unsigned long floorIntT = (unsigned long)floorT; if( floorT == t ) { return blendNoise3d( x, y, z, floorIntT ); } else { unsigned long ceilIntT = floorIntT + 1; // cosine interpolation // from http://freespace.virgin.net/hugo.elias/models/m_perlin.htm double ft = ( t - floorT ) * M_PI; double f = ( 1 - cos( ft ) ) * .5; return ( f ) * blendNoise3d( x, y, z, ceilIntT ) + ( 1 - f ) * blendNoise3d( x, y, z, floorIntT ); } } passage-4+dfsg1.orig/gamma256/prototypes/screenCompress/characterSprite.tga0000640000175000017500000000327210702733433025621 0ustar pabspabsGmmmmmmmmmm$ImmmmmmmmmmmmmmmmmmIImIImmmmmmmmmmmmmmmmmmmIImmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm$Immmm$ImmmmmmmmmmmmIImIImIImIImmmmmmmmmmmmmmmmIImIImmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmIIm$ImmmmmmmmmmmmmmmIIm$$Immmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm$Immmmmmmmmmmmmmmmmmm$$ImmmmmmmmmmmmmmmmmmIIm$$Immmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm$ImmmmmmmmmmmmmmmmmmmIImIImmmmmmmmmmmmmmmmmmmIImmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm$Immmm$ImmmmmmmmmmIImIImIImIImmmmmmmmmmmmmmmmIImIImmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmIIm$ImmmmmmmmmmmmmmmIIm$$Immmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm$Immmmmmmmmmmmmmmmmmm$$ImmmmmmmmmmmmmmmmmmIIm$$Immmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmpassage-4+dfsg1.orig/gamma256/prototypes/screenCompress/tileTemplate.png0000640000175000017500000000031710700231343025124 0ustar pabspabsPNG  IHDRV ?IDATH @h: 9 2b-ԐM"` Rf[WY+AL{"`_tt9C#jCzp 2+۷u]`JG$ #include #include #include // for memcpy #include // size of game image int width = 100; int height = 16; // size of screen int screenWidth = 640; int screenHeight = 480; // blow-up factor when projecting game onto screen int blowUpFactor = 6; //int blowUpFactor = 1; char fullScreen = false; double timeDelta = -0.1; //double timeDelta = -0.0; int mainFunction(); // must do this to prevent WinMain linker errors on win32 int main() { mainFunction(); } #include // the joystick to read from, or NULL if there's no available joystick SDL_Joystick *joystick; void catch_int(int sig_num) { printf( "Quiting...\n" ); SDL_Quit(); exit( 0 ); signal( SIGINT, catch_int ); } void blowupOntoScreen( Uint32 *inImage, int inWidth, int inHeight, int inBlowFactor, SDL_Surface *inScreen ) { int newWidth = inBlowFactor * inWidth; int newHeight = inBlowFactor * inHeight; int yOffset = ( inScreen->h - newHeight ) / 2; int xOffset = ( inScreen->w - newWidth ) / 2; int endY = yOffset + newHeight; int endX = xOffset + newWidth; Uint32 *pixels = (Uint32 *)( inScreen->pixels ); for( int y=yOffset; yw + x ] = inImage[ imageY * inWidth + imageX ]; } } } // values in range 0..1 Image *tileImage; int imageW, imageH; // dimensions of one tile. TileImage contains 13 tiles, stacked vertically, // with blank lines between tiles int tileW = 8; int tileH = 8; int numTileSets; // how wide the swath of a world is that uses a given tile set int tileSetWorldSpan = 200; // overlap during tile set transition int tileSetWorldOverlap = 50; // optimization (found with profiler) // values in range 0..255 double *tileRed; double *tileGreen; double *tileBlue; Image *spriteImage; int spriteW = 8; int spriteH = 8; double *spriteRed; double *spriteGreen; double *spriteBlue; int currentSpriteIndex = 2; double playerX, playerY; int playerRadius = spriteW / 2; int seed = time( NULL ); inline char isBlocked( int inX, int inY ) { // reduce to grid coordinates int gridX = inX / tileW; int gridY = inY / tileH; // wall along far left and top if( gridX <=0 || gridY <= 0 ) { return true; } // make a grid of empty spaces from which blocks can be // removed below to make a maze if( gridX % 2 !=0 && gridY % 2 != 0 ) { return false; } // blocks get denser as y increases double threshold = 1 - gridY / 20.0; double randValue = noise4d( gridX, gridY, seed, 0 ); return randValue > threshold; } char isSpriteTransparent( int inSpriteIndex ) { // take transparent color from corner return spriteRed[ inSpriteIndex ] == spriteRed[ 0 ] && spriteGreen[ inSpriteIndex ] == spriteGreen[ 0 ] && spriteBlue[ inSpriteIndex ] == spriteBlue[ 0 ]; } Uint32 sampleFromWorld( int inX, int inY, double inWeight = 1.0 ) { // consider sampling from sprite // player position centered on sprint left-to-right int spriteX = (int)( inX - playerX + spriteW / 2 ); // player position at sprite's feet int spriteY = (int)( inY - playerY + spriteH - 1); if( spriteX >= 0 && spriteX < spriteW && spriteY >= 0 && spriteY < spriteH ) { int spriteIndex = spriteY * spriteW + spriteX; // skip to appropriate sprite fram spriteIndex += currentSpriteIndex * spriteW * ( spriteH + 1 ); if( !isSpriteTransparent( spriteIndex ) ) { unsigned char r = (unsigned char)( inWeight * spriteRed[ spriteIndex ] ); unsigned char g = (unsigned char)( inWeight * spriteGreen[ spriteIndex ] ); unsigned char b = (unsigned char)( inWeight * spriteBlue[ spriteIndex ] ); return r << 16 | g << 8 | b; } } int tileIndex; if( !isBlocked( inX, inY ) ) { // empty tile tileIndex = 0; } else { int neighborsBlockedBinary = 0; if( isBlocked( inX, inY - tileH ) ) { // top neighborsBlockedBinary = neighborsBlockedBinary | 1; } if( isBlocked( inX + tileW, inY ) ) { // right neighborsBlockedBinary = neighborsBlockedBinary | 1 << 1; } if( isBlocked( inX, inY + tileH ) ) { // bottom neighborsBlockedBinary = neighborsBlockedBinary | 1 << 2; } if( isBlocked( inX - tileW, inY ) ) { // left neighborsBlockedBinary = neighborsBlockedBinary | 1 << 3; } // skip empty tile, treat as tile index neighborsBlockedBinary += 1; tileIndex = neighborsBlockedBinary; } // pick a tile set int netWorldSpan = tileSetWorldSpan + tileSetWorldOverlap; int tileSet = inX / netWorldSpan; int overhang = inX % netWorldSpan; if( inX < 0 ) { // fix to a constant tile set below 0 overhang = 0; tileSet = 0; } // is there blending with next tile set? int blendTileSet = tileSet + 1; double blendWeight = 0; if( overhang > tileSetWorldSpan ) { blendWeight = ( overhang - tileSetWorldSpan ) / (double) tileSetWorldOverlap; } // else 100% blend of our first tile set tileSet = tileSet % numTileSets; blendTileSet = blendTileSet % numTileSets; // make sure not negative if( tileSet < 0 ) { tileSet += numTileSets; } if( blendTileSet < 0 ) { blendTileSet += numTileSets; } // sample from tile image int imageY = inY % tileH; int imageX = inX % tileW; if( imageX < 0 ) { imageX += tileW; } if( imageY < 0 ) { imageY += tileH; } // offset to top left corner of tile int tileImageOffset = tileIndex * ( tileH + 1 ) * imageW + tileSet * (tileW + 1); int blendTileImageOffset = tileIndex * ( tileH + 1 ) * imageW + blendTileSet * (tileW + 1); int imageIndex = tileImageOffset + imageY * imageW + imageX; int blendImageIndex = blendTileImageOffset + imageY * imageW + imageX; unsigned char r = (unsigned char)( inWeight * ( (1-blendWeight) * tileRed[ imageIndex ] + blendWeight * tileRed[ blendImageIndex ] ) ); unsigned char g = (unsigned char)( inWeight * ( (1-blendWeight) * tileGreen[ imageIndex ] + blendWeight * tileGreen[ blendImageIndex ] ) ); unsigned char b = (unsigned char)( inWeight * ( (1-blendWeight) * tileBlue[ imageIndex ] + blendWeight * tileBlue[ blendImageIndex ] ) ); return r << 16 | g << 8 | b; } char getKeyDown( int inKeyCode ) { SDL_PumpEvents(); Uint8 *keys = SDL_GetKeyState( NULL ); return keys[ inKeyCode ] == SDL_PRESSED; } char getHatDown( Uint8 inHatPosition ) { if( joystick == NULL ) { return false; } SDL_JoystickUpdate(); Uint8 hatPosition = SDL_JoystickGetHat( joystick, 1 ); if( hatPosition & inHatPosition ) { return true; } else { return false; } } Image *readTGA( char *inFileName ) { File tileFile( NULL, inFileName ); FileInputStream tileStream( &tileFile ); TGAImageConverter converter; return converter.deformatImage( &tileStream ); } int mainFunction() { // let catch_int handle interrupt (^c) signal( SIGINT, catch_int ); // read in map tile tileImage = readTGA( "tileSet.tga" ); imageW = tileImage->getWidth(); imageH = tileImage->getHeight(); numTileSets = (imageW + 1) / (tileW + 1); int imagePixelCount = imageW * imageH; tileRed = new double[ imagePixelCount ]; tileGreen = new double[ imagePixelCount ]; tileBlue = new double[ imagePixelCount ]; for( int i=0; igetChannel(0)[ i ]; tileGreen[i] = 255 * tileImage->getChannel(1)[ i ]; tileBlue[i] = 255 * tileImage->getChannel(2)[ i ]; } // read in map tile spriteImage = readTGA( "characterSprite.tga" ); imagePixelCount = spriteImage->getWidth() * spriteImage->getHeight(); spriteRed = new double[ imagePixelCount ]; spriteGreen = new double[ imagePixelCount ]; spriteBlue = new double[ imagePixelCount ]; for( int i=0; igetChannel(0)[ i ]; spriteGreen[i] = 255 * spriteImage->getChannel(1)[ i ]; spriteBlue[i] = 255 * spriteImage->getChannel(2)[ i ]; } if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE ) < 0 ) { printf( "Couldn't initialize SDL: %s\n", SDL_GetError() ); return -1; } SDL_ShowCursor( SDL_DISABLE ); Uint32 flags = SDL_HWSURFACE | SDL_DOUBLEBUF; if( fullScreen ) { flags = flags | SDL_FULLSCREEN; } SDL_Surface *screen = SDL_SetVideoMode( screenWidth, screenHeight, 32, flags ); if ( screen == NULL ) { printf( "Couldn't set %dx%dx32 video mode: %s\n", screenWidth, screenHeight, SDL_GetError() ); return-1; } // try to open joystick int numJoysticks = SDL_NumJoysticks(); printf( "Found %d joysticks\n", numJoysticks ); if( numJoysticks > 0 ) { // open first one by default joystick = SDL_JoystickOpen( 1 ); if( joystick == NULL ) { printf( "Couldn't open joystick 1: %s\n", SDL_GetError() ); } int numHats = SDL_JoystickNumHats( joystick ); if( numHats <= 0 ) { printf( "No d-pad found on joystick\n" ); SDL_JoystickClose( joystick ); joystick = NULL; } } else { joystick = NULL; } Uint32 *pixels = (Uint32 *)( screen->pixels ); Uint32 *gameImage = new Uint32[ width * height ]; // first, fill the whole thing with black SDL_FillRect(screen, NULL, 0x00000000); // small area in center that we actually draw in, black around it int yOffset = ( screenHeight - height * blowUpFactor ) / 2; int xOffset = ( screenWidth - width * blowUpFactor ) / 2; double dX = 0; double dY = 0; int frameCount = 0; unsigned long startTime = time( NULL ); char done = false; double maxWorldX = 0; double minWorldX = 0; // start player position playerX = tileW; //playerX = 0; dX = tileW; playerY = 0 + height/2; dY = 0; while( !done ) { char someBlocksDrawn = false; for( int y=0; y maxDistance ) { cappedDistanceFromPlayer = maxDistance; } if( cappedDistanceFromPlayer < -maxDistance ) { cappedDistanceFromPlayer = -maxDistance; } // the world position we will sample from double worldX = x; // zone around player where no x compression happens int noCompressZone = 10; if( trueDistanceFromPlayer > noCompressZone ) { worldX = x + //(width/8) * // use true distance as a factor so that compression // continues at constant rate after we pass capped // distance // otherwise, compression stops after capped distance // Still... constant rate looks weird, so avoid // it by not letting it pass capped distance trueDistanceFromPlayer / 2 * ( pow( tan( ( ( cappedDistanceFromPlayer - noCompressZone ) / (double)( width - noCompressZone ) ) * M_PI / 2 ), 2) ); /* trueDistanceFromPlayer / 2 * ( tan( ( cappedDistanceFromPlayer / (double)( width - 0.5 ) ) * M_PI / 2 ) ); */ // simpler formula // actually, this does not approach 0 as // cappedDistanceFromPlayer approaches 0, so use tan // instead // ( trueDistanceFromPlayer / 2 ) * 100 // / pow( ( width - cappedDistanceFromPlayer ), 1.6 ); } else if( trueDistanceFromPlayer < - noCompressZone ) { worldX = x + //(width/8) * trueDistanceFromPlayer / 2 * ( pow( tan( ( ( - cappedDistanceFromPlayer - noCompressZone ) / (double)( width - noCompressZone ) ) * M_PI / 2 ), 2) ); /* trueDistanceFromPlayer / 2 * ( tan( ( - cappedDistanceFromPlayer / (double)( width - 0.5 ) ) * M_PI / 2 ) ); */ //( trueDistanceFromPlayer / 2 ) * 50 /// ( width + cappedDistanceFromPlayer ); } else { // inside no-compresison zone worldX = x; } //int worldX = x; worldX += dX; if( worldX > maxWorldX ) { maxWorldX = worldX; } if( worldX < minWorldX ) { minWorldX = worldX; } int worldY = (int)floor( y + dY ); // linear interpolation of two samples for worldX int intWorldX = (int)floor( worldX ); double bWeight = worldX - intWorldX; double aWeight = 1 - bWeight; Uint32 sampleA = sampleFromWorld( intWorldX, worldY, aWeight ); Uint32 sampleB = sampleFromWorld( intWorldX + 1, worldY, bWeight ); Uint32 combined = sampleB + sampleA; gameImage[ y * width + x ] = combined; } } // 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() ); } } blowupOntoScreen( gameImage, width, height, blowUpFactor, screen ); // unlock the screen if necessary if ( SDL_MUSTLOCK(screen) ) { SDL_UnlockSurface(screen); } if( ( screen->flags & SDL_DOUBLEBUF ) == SDL_DOUBLEBUF ) { // need to flip buffer SDL_Flip( screen ); printf( "double\n" ); } else { // just update center //SDL_UpdateRect( screen, yOffset, xOffset, width, height ); SDL_Flip( screen ); } int moveDelta = 1; if( getKeyDown( SDLK_LEFT ) || getHatDown( SDL_HAT_LEFT ) ) { if( currentSpriteIndex == 6 ) { currentSpriteIndex = 7; } else { currentSpriteIndex = 6; } if( !isBlocked( (int)( playerX - moveDelta ), (int)playerY ) ) { playerX -= moveDelta; if( playerX < 0 ) { // undo playerX += moveDelta; } else { // update screen position dX -= moveDelta; } } } else if( getKeyDown( SDLK_RIGHT ) || getHatDown( SDL_HAT_RIGHT )) { if( currentSpriteIndex == 2 ) { currentSpriteIndex = 3; } else { currentSpriteIndex = 2; } if( !isBlocked( (int)( playerX + moveDelta ), (int)playerY ) ) { dX += moveDelta; playerX += moveDelta; } } else if( getKeyDown( SDLK_UP ) || getHatDown( SDL_HAT_UP ) ) { if( currentSpriteIndex == 0 ) { currentSpriteIndex = 1; } else { currentSpriteIndex = 0; } if( !isBlocked( (int)playerX, (int)( playerY - moveDelta ) ) ) { playerY -= moveDelta; if( playerY < 0 ) { // undo playerY += moveDelta; } else { // update screen position dY -= moveDelta; } } } else if( getKeyDown( SDLK_DOWN ) || getHatDown( SDL_HAT_DOWN )) { if( currentSpriteIndex == 4 ) { currentSpriteIndex = 5; } else { currentSpriteIndex = 4; } if( !isBlocked( (int)playerX, (int)( playerY + moveDelta ) ) ) { dY += moveDelta; playerY += moveDelta; } } // check for events to quit SDL_Event event; while( SDL_PollEvent(&event) ) { switch( event.type ) { case SDL_KEYDOWN: switch( event.key.keysym.sym ) { case SDLK_q: done = true; break; } break; case SDL_QUIT: done = true; break; default: break; } } //t +=0.25; frameCount ++; // player position on screen inches forward dX += timeDelta; //dX -= 1; // stop after player has gone off right end of screen if( playerX - dX > width ) { dX = playerX - width; } } unsigned long netTime = time( NULL ) - startTime; double frameRate = frameCount / (double)netTime; printf( "Max world x = %f\n", maxWorldX ); printf( "Min world x = %f\n", minWorldX ); printf( "Frame rate = %f fps (%d frames)\n", frameRate, frameCount ); fflush( stdout ); delete tileImage; delete [] tileRed; delete [] tileGreen; delete [] tileBlue; delete spriteImage; delete [] spriteRed; delete [] spriteGreen; delete [] spriteBlue; if( joystick != NULL ) { SDL_JoystickClose( joystick ); } SDL_Quit(); } passage-4+dfsg1.orig/minorGems/0000750000175000017500000000000011376537576015214 5ustar pabspabspassage-4+dfsg1.orig/minorGems/common.h0000640000175000017500000000033707554101512016635 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 passage-4+dfsg1.orig/minorGems/ui/0000750000175000017500000000000011376536672015625 5ustar pabspabspassage-4+dfsg1.orig/minorGems/ui/event/0000750000175000017500000000000011376536672016746 5ustar pabspabspassage-4+dfsg1.orig/minorGems/ui/event/ActionListener.h0000640000175000017500000000132310452237532022025 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 passage-4+dfsg1.orig/minorGems/ui/event/ActionListenerList.h0000640000175000017500000000475711375054541022701 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 passage-4+dfsg1.orig/minorGems/ui/GUIComponent.h0000640000175000017500000000060007350771543020275 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 passage-4+dfsg1.orig/minorGems/ui/Keyboard.h0000640000175000017500000000316110447750664017535 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 passage-4+dfsg1.orig/minorGems/ui/ProgressBar.h0000640000175000017500000000257007205611501020211 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); } #endifpassage-4+dfsg1.orig/minorGems/ui/linux/0000750000175000017500000000000011376536672016764 5ustar pabspabspassage-4+dfsg1.orig/minorGems/ui/linux/MouseLinux.cpp0000640000175000017500000000270607274131574021600 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; } passage-4+dfsg1.orig/minorGems/ui/linux/KeyboardLinux.cpp0000640000175000017500000000644610447750665022261 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 */ passage-4+dfsg1.orig/minorGems/ui/SetMouseMac.cpp0000640000175000017500000000140107205611500020467 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() { }passage-4+dfsg1.orig/minorGems/ui/ProgressBar.cpp0000640000175000017500000000500207205611501020535 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(); }passage-4+dfsg1.orig/minorGems/ui/Mouse.h0000640000175000017500000000327407210735616017064 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 passage-4+dfsg1.orig/minorGems/ui/Plot.h0000640000175000017500000000262507205611501016677 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); } #endifpassage-4+dfsg1.orig/minorGems/ui/SetMouse.h0000640000175000017500000000042407205611500017517 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();passage-4+dfsg1.orig/minorGems/ui/Plot.cpp0000640000175000017500000000456107205611501017233 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} passage-4+dfsg1.orig/minorGems/io/0000750000175000017500000000000011376536644015616 5ustar pabspabspassage-4+dfsg1.orig/minorGems/io/Serializable.h0000640000175000017500000000345610340437222020364 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 passage-4+dfsg1.orig/minorGems/io/file/0000750000175000017500000000000011376536644016535 5ustar pabspabspassage-4+dfsg1.orig/minorGems/io/file/unix/0000750000175000017500000000000011376536644017520 5ustar pabspabspassage-4+dfsg1.orig/minorGems/io/file/unix/DirectoryUnix.cpp0000640000175000017500000000141207753761036023032 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; } } passage-4+dfsg1.orig/minorGems/io/file/FileInputStream.h0000640000175000017500000000740211364154511021747 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 passage-4+dfsg1.orig/minorGems/io/file/FileOutputStream.h0000640000175000017500000000667211356652402022163 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 passage-4+dfsg1.orig/minorGems/io/file/testPath.cpp0000640000175000017500000000112207522316361021020 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; } passage-4+dfsg1.orig/minorGems/io/file/File.h0000640000175000017500000005422311374544330017561 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 passage-4+dfsg1.orig/minorGems/io/file/UniversalFileIO.h0000640000175000017500000000572407205611501021675 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 ); } } #endifpassage-4+dfsg1.orig/minorGems/io/file/Path.h0000640000175000017500000003556411373324323017602 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 passage-4+dfsg1.orig/minorGems/io/file/linux/0000750000175000017500000000000011376536644017674 5ustar pabspabspassage-4+dfsg1.orig/minorGems/io/file/linux/PathLinux.cpp0000640000175000017500000000235111374544330022303 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; } } passage-4+dfsg1.orig/minorGems/io/file/Directory.h0000640000175000017500000000262207753761021020646 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 passage-4+dfsg1.orig/minorGems/io/file/win32/0000750000175000017500000000000011376536644017477 5ustar pabspabspassage-4+dfsg1.orig/minorGems/io/file/win32/DirectoryWin32.cpp0000640000175000017500000000140507753761036022772 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; } } passage-4+dfsg1.orig/minorGems/io/file/win32/dirent.cpp0000640000175000017500000000654307552400302021457 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 ); } passage-4+dfsg1.orig/minorGems/io/file/win32/PathWin32.cpp0000640000175000017500000000336011374544330021712 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; } } passage-4+dfsg1.orig/minorGems/io/file/win32/dirent.h0000640000175000017500000000327607554101513021130 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 passage-4+dfsg1.orig/minorGems/io/file/test/0000750000175000017500000000000011376536644017514 5ustar pabspabspassage-4+dfsg1.orig/minorGems/io/file/test/testPath.cpp0000640000175000017500000000112207776046015022006 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; } passage-4+dfsg1.orig/minorGems/io/file/test/testChildFiles.cpp0000640000175000017500000000223107776046015023122 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; } passage-4+dfsg1.orig/minorGems/io/serialPort/0000750000175000017500000000000011376536644017742 5ustar pabspabspassage-4+dfsg1.orig/minorGems/io/serialPort/testSerialPort.cpp0000640000175000017500000000101007624272636023422 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; } passage-4+dfsg1.orig/minorGems/io/serialPort/linux/0000750000175000017500000000000011376536644021101 5ustar pabspabspassage-4+dfsg1.orig/minorGems/io/serialPort/linux/SerialPortLinux.cpp0000640000175000017500000001477507643326107024721 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 ); } } passage-4+dfsg1.orig/minorGems/io/serialPort/SerialPortFromFile.cpp0000640000175000017500000000266207641141423024150 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; } } passage-4+dfsg1.orig/minorGems/io/serialPort/win32/0000750000175000017500000000000011376536644020704 5ustar pabspabspassage-4+dfsg1.orig/minorGems/io/serialPort/win32/COMPort.h0000640000175000017500000000672307643326110022334 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 passage-4+dfsg1.orig/minorGems/io/serialPort/win32/SerialPortWin32.cpp0000640000175000017500000001036507643326111024311 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(); } } passage-4+dfsg1.orig/minorGems/io/serialPort/win32/COMPort.cpp0000640000175000017500000002471107643367544022704 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 passage-4+dfsg1.orig/minorGems/io/serialPort/testSerialPortCompile0000750000175000017500000000011507624270527024156 0ustar pabspabsg++ -o testSerialPort -I../../.. linux/SerialPortLinux.cpp testSerialPort.cpppassage-4+dfsg1.orig/minorGems/io/serialPort/SerialPort.h0000640000175000017500000000430607643326042022172 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 passage-4+dfsg1.orig/minorGems/io/InputStream.h0000640000175000017500000000735010047466201020231 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 passage-4+dfsg1.orig/minorGems/io/TypeIO.h0000640000175000017500000000650610047466202017132 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 passage-4+dfsg1.orig/minorGems/io/pipedStreamTest.cpp0000640000175000017500000000305607244373534021440 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; } passage-4+dfsg1.orig/minorGems/io/linux/0000750000175000017500000000000011376536644016755 5ustar pabspabspassage-4+dfsg1.orig/minorGems/io/linux/TypeIOLinux.cpp0000640000175000017500000000524507473770515021661 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 passage-4+dfsg1.orig/minorGems/io/OutputStream.h0000640000175000017500000000716011374544330020435 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 passage-4+dfsg1.orig/minorGems/io/PipedStream.h0000640000175000017500000000765107554101513020200 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 passage-4+dfsg1.orig/minorGems/io/Stream.h0000640000175000017500000000513707554101513017213 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 passage-4+dfsg1.orig/minorGems/io/win32/0000750000175000017500000000000011376536644016560 5ustar pabspabspassage-4+dfsg1.orig/minorGems/io/win32/TypeIOWin32.cpp0000640000175000017500000000247107237354514021260 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; } passage-4+dfsg1.orig/minorGems/formats/0000750000175000017500000000000011376536643016661 5ustar pabspabspassage-4+dfsg1.orig/minorGems/formats/xml/0000750000175000017500000000000011376536643017461 5ustar pabspabspassage-4+dfsg1.orig/minorGems/formats/xml/XMLUtils.cpp0000640000175000017500000000470207540235637021647 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; } passage-4+dfsg1.orig/minorGems/formats/xml/XMLUtils.h0000640000175000017500000000134107540235637021310 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 passage-4+dfsg1.orig/minorGems/formats/html/0000750000175000017500000000000011376536643017625 5ustar pabspabspassage-4+dfsg1.orig/minorGems/formats/html/HTMLUtils.cpp0000640000175000017500000000215707540240755022116 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; } passage-4+dfsg1.orig/minorGems/formats/html/HTMLUtils.h0000640000175000017500000000131007540240755021551 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 passage-4+dfsg1.orig/minorGems/formats/encodingUtilsTestCompile0000750000175000017500000000021007733613350023551 0ustar pabspabsg++ -g -I../.. -o encodingUtilsTest encodingUtilsTest.cpp encodingUtils.cpp ../util/stringUtils.cpp ../util/StringBufferOutputStream.cpppassage-4+dfsg1.orig/minorGems/formats/encodingUtils.h0000640000175000017500000000423207733613350021634 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 passage-4+dfsg1.orig/minorGems/formats/encodingUtils.cpp0000640000175000017500000003143510027336105022162 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; } passage-4+dfsg1.orig/minorGems/formats/encodingUtilsTest.cpp0000640000175000017500000000232107733613350023024 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; } passage-4+dfsg1.orig/minorGems/util/0000750000175000017500000000000011376536672016165 5ustar pabspabspassage-4+dfsg1.orig/minorGems/util/development/0000750000175000017500000000000011462750600020470 5ustar pabspabspassage-4+dfsg1.orig/minorGems/util/development/leakTracer/0000750000175000017500000000000011376536672022564 5ustar pabspabspassage-4+dfsg1.orig/minorGems/util/development/leakTracer/LeakCheckAnalyze0000750000175000017500000000033110612151771025626 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 passage-4+dfsg1.orig/minorGems/util/development/leakTracer/leak-analyze0000750000175000017500000000636410002231613025044 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); passage-4+dfsg1.orig/minorGems/util/development/leakTracer/VERSION0000640000175000017500000000000410001775461023610 0ustar pabspabs2.3 passage-4+dfsg1.orig/minorGems/util/development/leakTracer/LeakCheck0000750000175000017500000000064010001775461024305 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 $@ passage-4+dfsg1.orig/minorGems/util/development/leakTracer/test.cc0000640000175000017500000000054110001775461024034 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 } passage-4+dfsg1.orig/minorGems/util/development/leakTracer/README.html0000640000175000017500000002270510001775461024377 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/

passage-4+dfsg1.orig/minorGems/util/development/leakTracer/Makefile0000640000175000017500000000262510001777407024215 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 passage-4+dfsg1.orig/minorGems/util/development/leakTracer/README0000640000175000017500000002130110001775461023423 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/ passage-4+dfsg1.orig/minorGems/util/development/leakTracer/LeakTracer.cc0000640000175000017500000003332011331117720025066 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: */ passage-4+dfsg1.orig/minorGems/util/development/memory/0000750000175000017500000000000011376536672022017 5ustar pabspabspassage-4+dfsg1.orig/minorGems/util/development/memory/debugMemory.cpp0000640000175000017500000000421307554553735025005 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 passage-4+dfsg1.orig/minorGems/util/development/memory/MemoryTrack.cpp0000640000175000017500000001620507554553734024766 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 passage-4+dfsg1.orig/minorGems/util/development/memory/testDebugMemory.cpp0000640000175000017500000000267707554421343025646 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; } passage-4+dfsg1.orig/minorGems/util/SettingsManager.h0000640000175000017500000002037411373324323021421 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 passage-4+dfsg1.orig/minorGems/util/CircularBuffer.h0000640000175000017500000000614107554101514021221 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 passage-4+dfsg1.orig/minorGems/util/SettingsManager.cpp0000640000175000017500000002127211374544330021755 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; } passage-4+dfsg1.orig/minorGems/util/random/0000750000175000017500000000000011376536672017445 5ustar pabspabspassage-4+dfsg1.orig/minorGems/util/random/Noise.h0000640000175000017500000000473207554101514020664 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 passage-4+dfsg1.orig/minorGems/util/random/testRandom.cpp0000640000175000017500000001141311142365151022251 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; } passage-4+dfsg1.orig/minorGems/util/random/CustomRandomSource.h0000640000175000017500000001146611175630012023377 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 passage-4+dfsg1.orig/minorGems/util/random/RandomSource.h0000640000175000017500000000401411133471650022200 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 passage-4+dfsg1.orig/minorGems/util/random/StdRandomSource.h0000640000175000017500000000641311133471650022660 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 passage-4+dfsg1.orig/minorGems/util/random/Noise.cpp0000640000175000017500000001625407220517221021215 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; } } passage-4+dfsg1.orig/minorGems/util/stringUtils.h0000640000175000017500000002153311373326622020657 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 passage-4+dfsg1.orig/minorGems/util/vectorTest.cpp0000640000175000017500000000425711325144546021031 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" ); } passage-4+dfsg1.orig/minorGems/util/log/0000750000175000017500000000000011376536672016746 5ustar pabspabspassage-4+dfsg1.orig/minorGems/util/log/PrintLog.h0000640000175000017500000000422611373324323020643 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 passage-4+dfsg1.orig/minorGems/util/log/AppLog.h0000640000175000017500000000715111373324323020267 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 passage-4+dfsg1.orig/minorGems/util/log/FileLog.h0000640000175000017500000000354211373324323020426 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 passage-4+dfsg1.orig/minorGems/util/log/Makefile0000640000175000017500000000235707436570640020411 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} passage-4+dfsg1.orig/minorGems/util/log/FileLog.cpp0000640000175000017500000000613111373324323020756 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 ); } passage-4+dfsg1.orig/minorGems/util/log/AppLog.cpp0000640000175000017500000000603211373324323020617 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(); } passage-4+dfsg1.orig/minorGems/util/log/Log.cpp0000640000175000017500000000057107436570021020163 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() { } passage-4+dfsg1.orig/minorGems/util/log/PrintLog.cpp0000640000175000017500000001116611373324323021177 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; } passage-4+dfsg1.orig/minorGems/util/log/testLog.cpp0000640000175000017500000000147207436570021021064 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; } passage-4+dfsg1.orig/minorGems/util/log/Log.h0000640000175000017500000000546311373324323017632 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 passage-4+dfsg1.orig/minorGems/util/StringBufferOutputStream.h0000640000175000017500000000277210047451312023321 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 passage-4+dfsg1.orig/minorGems/util/TranslationManager.cpp0000640000175000017500000002244111374544330022452 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; } } passage-4+dfsg1.orig/minorGems/util/StringBufferOutputStream.cpp0000640000175000017500000000227410047451312023651 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; } passage-4+dfsg1.orig/minorGems/util/stringUtils.cpp0000640000175000017500000002625711373326622021222 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; } } passage-4+dfsg1.orig/minorGems/util/SimpleVector.h0000640000175000017500000002702111373326622020742 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 passage-4+dfsg1.orig/minorGems/util/TranslationManager.h0000640000175000017500000001217311373324323022115 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 passage-4+dfsg1.orig/minorGems/util/printUtils.h0000640000175000017500000000102707554101514020476 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 passage-4+dfsg1.orig/minorGems/util/printUtils.cpp0000640000175000017500000000107407455450264021044 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; } passage-4+dfsg1.orig/minorGems/util/test/0000750000175000017500000000000011376536672017144 5ustar pabspabspassage-4+dfsg1.orig/minorGems/util/test/testSnprintf.mingw.out0000640000175000017500000000055610001574214023501 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 passage-4+dfsg1.orig/minorGems/util/test/testSnprintf.cpp0000640000175000017500000000232410001572273022332 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; } passage-4+dfsg1.orig/minorGems/crypto/hashes/sha1sumCompile0000750000175000017500000000011610053166076022605 0ustar pabspabsg++ -I../../.. -o sha1sum sha1sum.cpp sha1.cpp ../../formats/encodingUtils.cpppassage-4+dfsg1.orig/minorGems/crypto/hashes/sha1sum.cpp0000640000175000017500000000356111262434343022060 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 ); } passage-4+dfsg1.orig/minorGems/crypto/hashes/sha1.h0000640000175000017500000000765711330667201021007 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 passage-4+dfsg1.orig/minorGems/crypto/hashes/sha1Test.cpp0000640000175000017500000000476707733372451022215 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 } */passage-4+dfsg1.orig/minorGems/graphics/filters/0000750000175000017500000000000011376536643020456 5ustar pabspabspassage-4+dfsg1.orig/minorGems/graphics/filters/InvertFilter.h0000640000175000017500000000123307220517106023226 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 passage-4+dfsg1.orig/minorGems/graphics/filters/MedianFilter.h0000640000175000017500000000672407301027016023162 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 passage-4+dfsg1.orig/minorGems/graphics/filters/quickselect.h0000640000175000017500000000320607300520500023116 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 passage-4+dfsg1.orig/minorGems/graphics/filters/BoxBlurFilter.h0000640000175000017500000001367510500113717023344 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 passage-4+dfsg1.orig/minorGems/graphics/filters/ThresholdFilter.h0000640000175000017500000000265107220517106023720 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 passage-4+dfsg1.orig/minorGems/graphics/filters/SeamlessFilter.h0000640000175000017500000000740510506006133023534 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 passage-4+dfsg1.orig/minorGems/graphics/IconMap.h0000640000175000017500000001003607217533354020501 0ustar pabspabs// Jason Rohrer // IconMap.h /** * * Simple 2d icon map * * * Created 12-12-99 * Mods: * Jason Rohrer 12-13-99 Added numPixels member * Jason Rohrer 3-22-2000 Added support for drawing icon maps into an icon map * Jason Rohrer 12-17-2000 Added include of Color.h */ #ifndef ICON_MAP_INCLUDED #define ICON_MAP_INCLUDED #include #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 passage-4+dfsg1.orig/minorGems/graphics/3d/0000750000175000017500000000000011376536643017314 5ustar pabspabspassage-4+dfsg1.orig/minorGems/graphics/3d/LandscapePrimitive3D.h0000640000175000017500000000776707253033271023445 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 passage-4+dfsg1.orig/minorGems/graphics/3d/Primitive3DFactory.h0000640000175000017500000000646207261725075023162 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 passage-4+dfsg1.orig/minorGems/graphics/3d/Object3DFactory.h0000640000175000017500000000645207261725007022412 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 passage-4+dfsg1.orig/minorGems/graphics/3d/Object3D.h0000640000175000017500000001700607254677305021070 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 passage-4+dfsg1.orig/minorGems/graphics/3d/LathePrimitive3D.h0000640000175000017500000000650607252736762022614 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 passage-4+dfsg1.orig/minorGems/graphics/loadFile.cpp0000640000175000017500000000335007205611501021212 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); }passage-4+dfsg1.orig/minorGems/graphics/converters/0000750000175000017500000000000011376536643021200 5ustar pabspabspassage-4+dfsg1.orig/minorGems/graphics/converters/bmpformat.txt0000640000175000017500000000611307244265544023730 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 passage-4+dfsg1.orig/minorGems/graphics/converters/compileTestPNG0000750000175000017500000000022011341264416023741 0ustar pabspabsg++ -g -Wall -o testPNG -I../../.. testPNG.cpp PNGImageConverter.cpp ../../io/file/linux/PathLinux.cpp ../../system/unix/TimeUnix.cpp -lz -lpng passage-4+dfsg1.orig/minorGems/graphics/converters/LittleEndianImageConverter.h0000640000175000017500000000521207353214427026552 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 passage-4+dfsg1.orig/minorGems/graphics/converters/testPNG.cpp0000640000175000017500000000200411341264416023211 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; } passage-4+dfsg1.orig/minorGems/graphics/converters/unix/0000750000175000017500000000000011376536643022163 5ustar pabspabspassage-4+dfsg1.orig/minorGems/graphics/converters/unix/JPEGImageConverterUnix.cpp0000640000175000017500000004047710543537355027124 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 passage-4+dfsg1.orig/minorGems/graphics/converters/TGAImageConverter.h0000640000175000017500000002224711144105026024603 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 nothing done*/ { if(size * p->typesize > p->allocsize) { size_t newsize = size * p->typesize * 2; void* data = realloc(p->data, newsize); if(data) { p->allocsize = newsize; p->data = data; p->size = size; } else return 0; } else p->size = size; return 1; } static unsigned vector_resized(vector* p, size_t size, void dtor(void*)) /*resize and use destructor on elements if it gets smaller*/ { size_t i; if(size < p->size) for(i = size; i < p->size; i++) dtor(&((char*)(p->data))[i * p->typesize]); return vector_resize(p, size); } static void vector_cleanup(void* p) { ((vector*)p)->size = ((vector*)p)->allocsize = 0; free(((vector*)p)->data); ((vector*)p)->data = NULL; } static void vector_cleanupd(vector* p, void dtor(void*)) /*clear and use destructor on elements*/ { vector_resized(p, 0, dtor); vector_cleanup(p); } static void vector_init(vector* p, unsigned typesize) { p->data = NULL; p->size = p->allocsize = 0; p->typesize = typesize; } static void vector_swap(vector* p, vector* q) /*they're supposed to have the same typesize*/ { size_t tmp; void* tmpp; tmp = p->size; p->size = q->size; q->size = tmp; tmp = p->allocsize; p->allocsize = q->allocsize; q->allocsize = tmp; tmpp = p->data; p->data = q->data; q->data = tmpp; } static void* vector_get(vector* p, size_t index) { return &((char*)p->data)[index * p->typesize]; } #endif /*LODEPNG_COMPILE_ENCODER*/ #endif /*LODEPNG_COMPILE_ZLIB*/ /* /////////////////////////////////////////////////////////////////////////// */ #ifdef LODEPNG_COMPILE_ZLIB typedef struct uivector { unsigned* data; size_t size; /*size in number of unsigned longs*/ size_t allocsize; /*allocated size in bytes*/ } uivector; static void uivector_cleanup(void* p) { ((uivector*)p)->size = ((uivector*)p)->allocsize = 0; free(((uivector*)p)->data); ((uivector*)p)->data = NULL; } static unsigned uivector_resize(uivector* p, size_t size) /*returns 1 if success, 0 if failure ==> nothing done*/ { if(size * sizeof(unsigned) > p->allocsize) { size_t newsize = size * sizeof(unsigned) * 2; void* data = realloc(p->data, newsize); if(data) { p->allocsize = newsize; p->data = (unsigned*)data; p->size = size; } else return 0; } else p->size = size; return 1; } static unsigned uivector_resizev(uivector* p, size_t size, unsigned value) /*resize and give all new elements the value*/ { size_t oldsize = p->size, i; if(!uivector_resize(p, size)) return 0; for(i = oldsize; i < size; i++) p->data[i] = value; return 1; } static void uivector_init(uivector* p) { p->data = NULL; p->size = p->allocsize = 0; } #ifdef LODEPNG_COMPILE_ENCODER static unsigned uivector_push_back(uivector* p, unsigned c) /*returns 1 if success, 0 if failure ==> nothing done*/ { if(!uivector_resize(p, p->size + 1)) return 0; p->data[p->size - 1] = c; return 1; } static unsigned uivector_copy(uivector* p, const uivector* q) /*copy q to p, returns 1 if success, 0 if failure ==> nothing done*/ { size_t i; if(!uivector_resize(p, q->size)) return 0; for(i = 0; i < q->size; i++) p->data[i] = q->data[i]; return 1; } static void uivector_swap(uivector* p, uivector* q) { size_t tmp; unsigned* tmpp; tmp = p->size; p->size = q->size; q->size = tmp; tmp = p->allocsize; p->allocsize = q->allocsize; q->allocsize = tmp; tmpp = p->data; p->data = q->data; q->data = tmpp; } #endif /*LODEPNG_COMPILE_ENCODER*/ #endif /*LODEPNG_COMPILE_ZLIB*/ /* /////////////////////////////////////////////////////////////////////////// */ typedef struct ucvector { unsigned char* data; size_t size; /*used size*/ size_t allocsize; /*allocated size*/ } ucvector; static void ucvector_cleanup(void* p) { ((ucvector*)p)->size = ((ucvector*)p)->allocsize = 0; free(((ucvector*)p)->data); ((ucvector*)p)->data = NULL; } static unsigned ucvector_resize(ucvector* p, size_t size) /*returns 1 if success, 0 if failure ==> nothing done*/ { if(size * sizeof(unsigned) > p->allocsize) { size_t newsize = size * sizeof(unsigned) * 2; void* data = realloc(p->data, newsize); if(data) { p->allocsize = newsize; p->data = (unsigned char*)data; p->size = size; } else return 0; /*error: not enough memory*/ } else p->size = size; return 1; } #ifdef LODEPNG_COMPILE_DECODER #ifdef LODEPNG_COMPILE_PNG static unsigned ucvector_resizev(ucvector* p, size_t size, unsigned char value) /*resize and give all new elements the value*/ { size_t oldsize = p->size, i; if(!ucvector_resize(p, size)) return 0; for(i = oldsize; i < size; i++) p->data[i] = value; return 1; } #endif /*LODEPNG_COMPILE_PNG*/ #endif /*LODEPNG_COMPILE_DECODER*/ static void ucvector_init(ucvector* p) { p->data = NULL; p->size = p->allocsize = 0; } #ifdef LODEPNG_COMPILE_ZLIB /*you can both convert from vector to buffer&size and vica versa*/ static void ucvector_init_buffer(ucvector* p, unsigned char* buffer, size_t size) { p->data = buffer; p->allocsize = p->size = size; } #endif /*LODEPNG_COMPILE_ZLIB*/ static unsigned ucvector_push_back(ucvector* p, unsigned char c) /*returns 1 if success, 0 if failure ==> nothing done*/ { if(!ucvector_resize(p, p->size + 1)) return 0; p->data[p->size - 1] = c; return 1; } /* /////////////////////////////////////////////////////////////////////////// */ #ifdef LODEPNG_COMPILE_PNG #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS static unsigned string_resize(char** out, size_t size) /*returns 1 if success, 0 if failure ==> nothing done*/ { char* data = (char*)realloc(*out, size + 1); if(data) { data[size] = 0; /*null termination char*/ *out = data; } return data != 0; } static void string_init(char** out) /*init a {char*, size_t} pair for use as string*/ { *out = NULL; string_resize(out, 0); } static void string_cleanup(char** out) /*free the above pair again*/ { free(*out); *out = NULL; } static void string_set(char** out, const char* in) { size_t insize = strlen(in), i = 0; if(string_resize(out, insize)) for(i = 0; i < insize; i++) (*out)[i] = in[i]; } #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ #endif /*LODEPNG_COMPILE_PNG*/ #ifdef LODEPNG_COMPILE_ZLIB /* ////////////////////////////////////////////////////////////////////////// */ /* / Reading and writing single bits and bytes from/to stream for Deflate / */ /* ////////////////////////////////////////////////////////////////////////// */ #ifdef LODEPNG_COMPILE_ENCODER static void addBitToStream(size_t* bitpointer, ucvector* bitstream, unsigned char bit) { if((*bitpointer) % 8 == 0) ucvector_push_back(bitstream, 0); /*add a new byte at the end*/ (bitstream->data[bitstream->size - 1]) |= (bit << ((*bitpointer) & 0x7)); /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/ (*bitpointer)++; } static void addBitsToStream(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits) { size_t i; for(i = 0; i < nbits; i++) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> i) & 1)); } static void addBitsToStreamReversed(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits) { size_t i; for(i = 0; i < nbits; i++) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> (nbits - 1 - i)) & 1)); } #endif /*LODEPNG_COMPILE_ENCODER*/ #ifdef LODEPNG_COMPILE_DECODER static unsigned char readBitFromStream(size_t* bitpointer, const unsigned char* bitstream) { unsigned char result = (unsigned char)((bitstream[(*bitpointer) >> 3] >> ((*bitpointer) & 0x7)) & 1); (*bitpointer)++; return result; } static unsigned readBitsFromStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) { unsigned result = 0, i; for(i = 0; i < nbits; i++) result += ((unsigned)readBitFromStream(bitpointer, bitstream)) << i; return result; } #endif /*LODEPNG_COMPILE_DECODER*/ /* ////////////////////////////////////////////////////////////////////////// */ /* / Deflate - Huffman / */ /* ////////////////////////////////////////////////////////////////////////// */ #define FIRST_LENGTH_CODE_INDEX 257 #define LAST_LENGTH_CODE_INDEX 285 #define NUM_DEFLATE_CODE_SYMBOLS 288 /*256 literals, the end code, some length codes, and 2 unused codes*/ #define NUM_DISTANCE_SYMBOLS 32 /*the distance codes have their own symbols, 30 used, 2 unused*/ #define NUM_CODE_LENGTH_CODES 19 /*the code length codes. 0-15: code lengths, 16: copy previous 3-6 times, 17: 3-10 zeros, 18: 11-138 zeros*/ static const unsigned LENGTHBASE[29] /*the base lengths represented by codes 257-285*/ = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258}; static const unsigned LENGTHEXTRA[29] /*the extra bits used by codes 257-285 (added to base length)*/ = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; static const unsigned DISTANCEBASE[30] /*the base backwards distances (the bits of distance codes appear after length codes and use their own huffman tree)*/ = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577}; static const unsigned DISTANCEEXTRA[30] /*the extra bits of backwards distances (added to base)*/ = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; static const unsigned CLCL[NUM_CODE_LENGTH_CODES] /*the order in which "code length alphabet code lengths" are stored, out of this the huffman tree of the dynamic huffman tree lengths is generated*/ = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; /* /////////////////////////////////////////////////////////////////////////// */ #ifdef LODEPNG_COMPILE_ENCODER /*terminology used for the package-merge algorithm and the coin collector's problem*/ typedef struct Coin /*a coin can be multiple coins (when they're merged)*/ { uivector symbols; float weight; /*the sum of all weights in this coin*/ } Coin; static void Coin_init(Coin* c) { uivector_init(&c->symbols); } static void Coin_cleanup(void* c) /*void* so that this dtor can be given as function pointer to the vector resize function*/ { uivector_cleanup(&((Coin*)c)->symbols); } static void Coin_copy(Coin* c1, const Coin* c2) { c1->weight = c2->weight; uivector_copy(&c1->symbols, &c2->symbols); } static void addCoins(Coin* c1, const Coin* c2) { unsigned i; for(i = 0; i < c2->symbols.size; i++) uivector_push_back(&c1->symbols, c2->symbols.data[i]); c1->weight += c2->weight; } static void Coin_sort(Coin* data, size_t amount) /*combsort*/ { size_t gap = amount; unsigned char swapped = 0; while(gap > 1 || swapped) { size_t i; gap = (gap * 10) / 13; /*shrink factor 1.3*/ if(gap == 9 || gap == 10) gap = 11; /*combsort11*/ if(gap < 1) gap = 1; swapped = 0; for(i = 0; i < amount - gap; i++) { size_t j = i + gap; if(data[j].weight < data[i].weight) { float temp = data[j].weight; data[j].weight = data[i].weight; data[i].weight = temp; uivector_swap(&data[i].symbols, &data[j].symbols); swapped = 1; } } } } #endif /*LODEPNG_COMPILE_ENCODER*/ typedef struct HuffmanTree { uivector tree2d; uivector tree1d; uivector lengths; /*the lengths of the codes of the 1d-tree*/ unsigned maxbitlen; /*maximum number of bits a single code can get*/ unsigned numcodes; /*number of symbols in the alphabet = number of codes*/ } HuffmanTree; /*function used for debug purposes*/ /*#include static void HuffmanTree_draw(HuffmanTree* tree) { std::cout << "tree. length: " << tree->numcodes << " maxbitlen: " << tree->maxbitlen << std::endl; for(size_t i = 0; i < tree->tree1d.size; i++) { if(tree->lengths.data[i]) std::cout << i << " " << tree->tree1d.data[i] << " " << tree->lengths.data[i] << std::endl; } std::cout << std::endl; }*/ static void HuffmanTree_init(HuffmanTree* tree) { uivector_init(&tree->tree2d); uivector_init(&tree->tree1d); uivector_init(&tree->lengths); } static void HuffmanTree_cleanup(HuffmanTree* tree) { uivector_cleanup(&tree->tree2d); uivector_cleanup(&tree->tree1d); uivector_cleanup(&tree->lengths); } /*the tree representation used by the decoder. return value is error*/ static unsigned HuffmanTree_make2DTree(HuffmanTree* tree) { unsigned nodefilled = 0; /*up to which node it is filled*/ unsigned treepos = 0; /*position in the tree (1 of the numcodes columns)*/ unsigned n, i; if(!uivector_resize(&tree->tree2d, tree->numcodes * 2)) return 9901; /*if failed return not enough memory error*/ /*convert tree1d[] to tree2d[][]. In the 2D array, a value of 32767 means uninited, a value >= numcodes is an address to another bit, a value < numcodes is a code. The 2 rows are the 2 possible bit values (0 or 1), there are as many columns as codes - 1 a good huffmann tree has N * 2 - 1 nodes, of which N - 1 are internal nodes. Here, the internal nodes are stored (what their 0 and 1 option point to). There is only memory for such good tree currently, if there are more nodes (due to too long length codes), error 55 will happen*/ for(n = 0; n < tree->numcodes * 2; n++) tree->tree2d.data[n] = 32767; /*32767 here means the tree2d isn't filled there yet*/ for(n = 0; n < tree->numcodes; n++) /*the codes*/ for(i = 0; i < tree->lengths.data[n]; i++) /*the bits for this code*/ { unsigned char bit = (unsigned char)((tree->tree1d.data[n] >> (tree->lengths.data[n] - i - 1)) & 1); if(treepos > tree->numcodes - 2) return 55; /*error 55: oversubscribed; see description in header*/ if(tree->tree2d.data[2 * treepos + bit] == 32767) /*not yet filled in*/ { if(i + 1 == tree->lengths.data[n]) /*last bit*/ { tree->tree2d.data[2 * treepos + bit] = n; /*put the current code in it*/ treepos = 0; } else /*put address of the next step in here, first that address has to be found of course (it's just nodefilled + 1)...*/ { nodefilled++; tree->tree2d.data[2 * treepos + bit] = nodefilled + tree->numcodes; /*addresses encoded with numcodes added to it*/ treepos = nodefilled; } } else treepos = tree->tree2d.data[2 * treepos + bit] - tree->numcodes; } for(n = 0; n < tree->numcodes * 2; n++) if(tree->tree2d.data[n] == 32767) tree->tree2d.data[n] = 0; /*remove possible remaining 32767's*/ return 0; } static unsigned HuffmanTree_makeFromLengths2(HuffmanTree* tree) /*given that numcodes, lengths and maxbitlen are already filled in correctly. return value is error.*/ { uivector blcount; uivector nextcode; unsigned bits, n, error = 0; uivector_init(&blcount); uivector_init(&nextcode); if(!uivector_resize(&tree->tree1d, tree->numcodes) || !uivector_resizev(&blcount, tree->maxbitlen + 1, 0) || !uivector_resizev(&nextcode, tree->maxbitlen + 1, 0)) error = 9902; if(!error) { /*step 1: count number of instances of each code length*/ for(bits = 0; bits < tree->numcodes; bits++) blcount.data[tree->lengths.data[bits]]++; /*step 2: generate the nextcode values*/ for(bits = 1; bits <= tree->maxbitlen; bits++) nextcode.data[bits] = (nextcode.data[bits - 1] + blcount.data[bits - 1]) << 1; /*step 3: generate all the codes*/ for(n = 0; n < tree->numcodes; n++) if(tree->lengths.data[n] != 0) tree->tree1d.data[n] = nextcode.data[tree->lengths.data[n]]++; } uivector_cleanup(&blcount); uivector_cleanup(&nextcode); if(!error) return HuffmanTree_make2DTree(tree); else return error; } /*given the code lengths (as stored in the PNG file), generate the tree as defined by Deflate. maxbitlen is the maximum bits that a code in the tree can have. return value is error.*/ static unsigned HuffmanTree_makeFromLengths(HuffmanTree* tree, const unsigned* bitlen, size_t numcodes, unsigned maxbitlen) { unsigned i; if(!uivector_resize(&tree->lengths, numcodes)) return 9903; for(i = 0; i < numcodes; i++) tree->lengths.data[i] = bitlen[i]; tree->numcodes = (unsigned)numcodes; /*number of symbols*/ tree->maxbitlen = maxbitlen; return HuffmanTree_makeFromLengths2(tree); } #ifdef LODEPNG_COMPILE_ENCODER static unsigned HuffmanTree_fillInCoins(vector* coins, const unsigned* frequencies, unsigned numcodes, size_t sum) { unsigned i; for(i = 0; i < numcodes; i++) { Coin* coin; if(frequencies[i] == 0) continue; /*it's important to exclude symbols that aren't present*/ if(!vector_resize(coins, coins->size + 1)) { vector_cleanup(coins); return 9904; } coin = (Coin*)(vector_get(coins, coins->size - 1)); Coin_init(coin); coin->weight = frequencies[i] / (float)sum; uivector_push_back(&coin->symbols, i); } if(coins->size) Coin_sort((Coin*)coins->data, coins->size); return 0; } static unsigned HuffmanTree_makeFromFrequencies(HuffmanTree* tree, const unsigned* frequencies, size_t numcodes, unsigned maxbitlen) { unsigned i, j; size_t sum = 0, numpresent = 0; unsigned error = 0; vector prev_row; /*type Coin, the previous row of coins*/ vector coins; /*type Coin, the coins of the currently calculated row*/ tree->maxbitlen = maxbitlen; for(i = 0; i < numcodes; i++) { if(frequencies[i] > 0) { numpresent++; sum += frequencies[i]; } } if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/ tree->numcodes = (unsigned)numcodes; /*number of symbols*/ uivector_resize(&tree->lengths, 0); if(!uivector_resizev(&tree->lengths, tree->numcodes, 0)) return 9905; if(numpresent == 0) /*there are no symbols at all, in that case add one symbol of value 0 to the tree (see RFC 1951 section 3.2.7) */ { tree->lengths.data[0] = 1; return HuffmanTree_makeFromLengths2(tree); } else if(numpresent == 1) /*the package merge algorithm gives wrong results if there's only one symbol (theoretically 0 bits would then suffice, but we need a proper symbol for zlib)*/ { for(i = 0; i < numcodes; i++) if(frequencies[i]) tree->lengths.data[i] = 1; return HuffmanTree_makeFromLengths2(tree); } vector_init(&coins, sizeof(Coin)); vector_init(&prev_row, sizeof(Coin)); /*Package-Merge algorithm represented by coin collector's problem For every symbol, maxbitlen coins will be created*/ /*first row, lowest denominator*/ error = HuffmanTree_fillInCoins(&coins, frequencies, tree->numcodes, sum); if(!error) { for(j = 1; j <= maxbitlen && !error; j++) /*each of the remaining rows*/ { vector_swap(&coins, &prev_row); /*swap instead of copying*/ if(!vector_resized(&coins, 0, Coin_cleanup)) { error = 9906; break; } for(i = 0; i + 1 < prev_row.size; i += 2) { if(!vector_resize(&coins, coins.size + 1)) { error = 9907; break; } Coin_init((Coin*)vector_get(&coins, coins.size - 1)); Coin_copy((Coin*)vector_get(&coins, coins.size - 1), (Coin*)vector_get(&prev_row, i)); addCoins((Coin*)vector_get(&coins, coins.size - 1), (Coin*)vector_get(&prev_row, i + 1)); /*merge the coins into packages*/ } if(j < maxbitlen) { error = HuffmanTree_fillInCoins(&coins, frequencies, tree->numcodes, sum); } } } if(!error) { /*keep the coins with lowest weight, so that they add up to the amount of symbols - 1*/ vector_resized(&coins, numpresent - 1, Coin_cleanup); /*calculate the lenghts of each symbol, as the amount of times a coin of each symbol is used*/ for(i = 0; i < coins.size; i++) { Coin* coin = (Coin*)vector_get(&coins, i); for(j = 0; j < coin->symbols.size; j++) tree->lengths.data[coin->symbols.data[j]]++; } error = HuffmanTree_makeFromLengths2(tree); } vector_cleanupd(&coins, Coin_cleanup); vector_cleanupd(&prev_row, Coin_cleanup); return error; } static unsigned HuffmanTree_getCode(const HuffmanTree* tree, unsigned index) { return tree->tree1d.data[index]; } static unsigned HuffmanTree_getLength(const HuffmanTree* tree, unsigned index) { return tree->lengths.data[index]; } #endif /*LODEPNG_COMPILE_ENCODER*/ /*get the tree of a deflated block with fixed tree, as specified in the deflate specification*/ static unsigned generateFixedTree(HuffmanTree* tree) { unsigned i, error = 0; uivector bitlen; uivector_init(&bitlen); if(!uivector_resize(&bitlen, NUM_DEFLATE_CODE_SYMBOLS)) error = 9909; if(!error) { /*288 possible codes: 0-255=literals, 256=endcode, 257-285=lengthcodes, 286-287=unused*/ for(i = 0; i <= 143; i++) bitlen.data[i] = 8; for(i = 144; i <= 255; i++) bitlen.data[i] = 9; for(i = 256; i <= 279; i++) bitlen.data[i] = 7; for(i = 280; i <= 287; i++) bitlen.data[i] = 8; error = HuffmanTree_makeFromLengths(tree, bitlen.data, NUM_DEFLATE_CODE_SYMBOLS, 15); } uivector_cleanup(&bitlen); return error; } static unsigned generateDistanceTree(HuffmanTree* tree) { unsigned i, error = 0; uivector bitlen; uivector_init(&bitlen); if(!uivector_resize(&bitlen, NUM_DISTANCE_SYMBOLS)) error = 9910; /*there are 32 distance codes, but 30-31 are unused*/ if(!error) { for(i = 0; i < NUM_DISTANCE_SYMBOLS; i++) bitlen.data[i] = 5; error = HuffmanTree_makeFromLengths(tree, bitlen.data, NUM_DISTANCE_SYMBOLS, 15); } uivector_cleanup(&bitlen); return error; } #ifdef LODEPNG_COMPILE_DECODER /*Decodes a symbol from the tree if decoded is true, then result contains the symbol, otherwise it contains something unspecified (because the symbol isn't fully decoded yet) bit is the bit that was just read from the stream you have to decode a full symbol (let the decode function return true) before you can try to decode another one, otherwise the state isn't reset return value is error.*/ static unsigned HuffmanTree_decode(const HuffmanTree* tree, unsigned* decoded, unsigned* result, unsigned* treepos, unsigned char bit) { if((*treepos) >= tree->numcodes) return 11; /*error: it appeared outside the codetree*/ (*result) = tree->tree2d.data[2 * (*treepos) + bit]; (*decoded) = ((*result) < tree->numcodes); if(*decoded) (*treepos) = 0; else (*treepos) = (*result) - tree->numcodes; return 0; } static unsigned huffmanDecodeSymbol(unsigned int* error, const unsigned char* in, size_t* bp, const HuffmanTree* codetree, size_t inlength) { unsigned treepos = 0, decoded, ct; for(;;) { unsigned char bit; if(((*bp) & 0x07) == 0 && ((*bp) >> 3) > inlength) { *error = 10; return 0; } /*error: end of input memory reached without endcode*/ bit = readBitFromStream(bp, in); *error = HuffmanTree_decode(codetree, &decoded, &ct, &treepos, bit); if(*error) return 0; /*stop, an error happened*/ if(decoded) return ct; } } #endif /*LODEPNG_COMPILE_DECODER*/ #ifdef LODEPNG_COMPILE_DECODER /* ////////////////////////////////////////////////////////////////////////// */ /* / Inflator / */ /* ////////////////////////////////////////////////////////////////////////// */ /*get the tree of a deflated block with fixed tree, as specified in the deflate specification*/ static void getTreeInflateFixed(HuffmanTree* tree, HuffmanTree* treeD) { /*error checking not done, this is fixed stuff, it works, it doesn't depend on the image*/ generateFixedTree(tree); generateDistanceTree(treeD); } /*get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree*/ static unsigned getTreeInflateDynamic(HuffmanTree* codetree, HuffmanTree* codetreeD, HuffmanTree* codelengthcodetree, const unsigned char* in, size_t* bp, size_t inlength) { /*make sure that length values that aren't filled in will be 0, or a wrong tree will be generated*/ /*C-code note: use no "return" between ctor and dtor of an uivector!*/ unsigned error = 0; unsigned n, HLIT, HDIST, HCLEN, i; uivector bitlen; uivector bitlenD; uivector codelengthcode; if((*bp) >> 3 >= inlength - 2) { return 49; } /*the bit pointer is or will go past the memory*/ HLIT = readBitsFromStream(bp, in, 5) + 257; /*number of literal/length codes + 257. Unlike the spec, the value 257 is added to it here already*/ HDIST = readBitsFromStream(bp, in, 5) + 1; /*number of distance codes. Unlike the spec, the value 1 is added to it here already*/ HCLEN = readBitsFromStream(bp, in, 4) + 4; /*number of code length codes. Unlike the spec, the value 4 is added to it here already*/ /*read the code length codes out of 3 * (amount of code length codes) bits*/ uivector_init(&codelengthcode); if(!uivector_resize(&codelengthcode, NUM_CODE_LENGTH_CODES)) error = 9911; if(!error) { for(i = 0; i < NUM_CODE_LENGTH_CODES; i++) { if(i < HCLEN) codelengthcode.data[CLCL[i]] = readBitsFromStream(bp, in, 3); else codelengthcode.data[CLCL[i]] = 0; /*if not, it must stay 0*/ } error = HuffmanTree_makeFromLengths(codelengthcodetree, codelengthcode.data, codelengthcode.size, 7); } uivector_cleanup(&codelengthcode); if(error) return error; /*now we can use this tree to read the lengths for the tree that this function will return*/ uivector_init(&bitlen); uivector_resizev(&bitlen, NUM_DEFLATE_CODE_SYMBOLS, 0); uivector_init(&bitlenD); uivector_resizev(&bitlenD, NUM_DISTANCE_SYMBOLS, 0); i = 0; if(!bitlen.data || !bitlenD.data) error = 9912; else while(i < HLIT + HDIST) /*i is the current symbol we're reading in the part that contains the code lengths of lit/len codes and dist codes*/ { unsigned code = huffmanDecodeSymbol(&error, in, bp, codelengthcodetree, inlength); if(error) break; if(code <= 15) /*a length code*/ { if(i < HLIT) bitlen.data[i] = code; else bitlenD.data[i - HLIT] = code; i++; } else if(code == 16) /*repeat previous*/ { unsigned replength = 3; /*read in the 2 bits that indicate repeat length (3-6)*/ unsigned value; /*set value to the previous code*/ if((*bp) >> 3 >= inlength) { error = 50; break; } /*error, bit pointer jumps past memory*/ replength += readBitsFromStream(bp, in, 2); if((i - 1) < HLIT) value = bitlen.data[i - 1]; else value = bitlenD.data[i - HLIT - 1]; /*repeat this value in the next lengths*/ for(n = 0; n < replength; n++) { if(i >= HLIT + HDIST) { error = 13; break; } /*error: i is larger than the amount of codes*/ if(i < HLIT) bitlen.data[i] = value; else bitlenD.data[i - HLIT] = value; i++; } } else if(code == 17) /*repeat "0" 3-10 times*/ { unsigned replength = 3; /*read in the bits that indicate repeat length*/ if((*bp) >> 3 >= inlength) { error = 50; break; } /*error, bit pointer jumps past memory*/ replength += readBitsFromStream(bp, in, 3); /*repeat this value in the next lengths*/ for(n = 0; n < replength; n++) { if(i >= HLIT + HDIST) { error = 14; break; } /*error: i is larger than the amount of codes*/ if(i < HLIT) bitlen.data[i] = 0; else bitlenD.data[i - HLIT] = 0; i++; } } else if(code == 18) /*repeat "0" 11-138 times*/ { unsigned replength = 11; /*read in the bits that indicate repeat length*/ if((*bp) >> 3 >= inlength) { error = 50; break; } /*error, bit pointer jumps past memory*/ replength += readBitsFromStream(bp, in, 7); /*repeat this value in the next lengths*/ for(n = 0; n < replength; n++) { if(i >= HLIT + HDIST) { error = 15; break; } /*error: i is larger than the amount of codes*/ if(i < HLIT) bitlen.data[i] = 0; else bitlenD.data[i - HLIT] = 0; i++; } } else { error = 16; break; } /*error: somehow an unexisting code appeared. This can never happen.*/ } if(!error && bitlen.data[256] == 0) { error = 64; } /*the length of the end code 256 must be larger than 0*/ /*now we've finally got HLIT and HDIST, so generate the code trees, and the function is done*/ if(!error) error = HuffmanTree_makeFromLengths(codetree, &bitlen.data[0], bitlen.size, 15); if(!error) error = HuffmanTree_makeFromLengths(codetreeD, &bitlenD.data[0], bitlenD.size, 15); uivector_cleanup(&bitlen); uivector_cleanup(&bitlenD); return error; } /*inflate a block with dynamic of fixed Huffman tree*/ static unsigned inflateHuffmanBlock(ucvector* out, const unsigned char* in, size_t* bp, size_t* pos, size_t inlength, unsigned btype) { unsigned endreached = 0, error = 0; HuffmanTree codetree; /*287, the code tree for Huffman codes*/ HuffmanTree codetreeD; /*31, the code tree for distance codes*/ HuffmanTree_init(&codetree); HuffmanTree_init(&codetreeD); if(btype == 1) getTreeInflateFixed(&codetree, &codetreeD); else if(btype == 2) { HuffmanTree codelengthcodetree; /*18, the code tree for code length codes*/ HuffmanTree_init(&codelengthcodetree); error = getTreeInflateDynamic(&codetree, &codetreeD, &codelengthcodetree, in, bp, inlength); HuffmanTree_cleanup(&codelengthcodetree); } while(!endreached && !error) { unsigned code = huffmanDecodeSymbol(&error, in, bp, &codetree, inlength); if(error) break; /*some error happened in the above function*/ if(code == 256) endreached = 1; /*end code*/ else if(code <= 255) /*literal symbol*/ { if((*pos) >= out->size) ucvector_resize(out, ((*pos) + 1) * 2); /*reserve more room at once*/ if((*pos) >= out->size) { error = 9913; break; } /*not enough memory*/ out->data[(*pos)] = (unsigned char)(code); (*pos)++; } else if(code >= FIRST_LENGTH_CODE_INDEX && code <= LAST_LENGTH_CODE_INDEX) /*length code*/ { /*part 1: get length base*/ size_t length = LENGTHBASE[code - FIRST_LENGTH_CODE_INDEX]; unsigned codeD, distance, numextrabitsD; size_t start, forward, backward, numextrabits; /*part 2: get extra bits and add the value of that to length*/ numextrabits = LENGTHEXTRA[code - FIRST_LENGTH_CODE_INDEX]; if(((*bp) >> 3) >= inlength) { error = 51; break; } /*error, bit pointer will jump past memory*/ length += readBitsFromStream(bp, in, numextrabits); /*part 3: get distance code*/ codeD = huffmanDecodeSymbol(&error, in, bp, &codetreeD, inlength); if(error) break; if(codeD > 29) { error = 18; break; } /*error: invalid distance code (30-31 are never used)*/ distance = DISTANCEBASE[codeD]; /*part 4: get extra bits from distance*/ numextrabitsD = DISTANCEEXTRA[codeD]; if(((*bp) >> 3) >= inlength) { error = 51; break; } /*error, bit pointer will jump past memory*/ distance += readBitsFromStream(bp, in, numextrabitsD); /*part 5: fill in all the out[n] values based on the length and dist*/ start = (*pos); backward = start - distance; if((*pos) + length >= out->size) ucvector_resize(out, ((*pos) + length) * 2); /*reserve more room at once*/ if((*pos) + length >= out->size) { error = 9914; break; } /*not enough memory*/ for(forward = 0; forward < length; forward++) { out->data[(*pos)] = out->data[backward]; (*pos)++; backward++; if(backward >= start) backward = start - distance; } } } HuffmanTree_cleanup(&codetree); HuffmanTree_cleanup(&codetreeD); return error; } static unsigned inflateNoCompression(ucvector* out, const unsigned char* in, size_t* bp, size_t* pos, size_t inlength) { /*go to first boundary of byte*/ size_t p; unsigned LEN, NLEN, n, error = 0; while(((*bp) & 0x7) != 0) (*bp)++; p = (*bp) / 8; /*byte position*/ /*read LEN (2 bytes) and NLEN (2 bytes)*/ if(p >= inlength - 4) return 52; /*error, bit pointer will jump past memory*/ LEN = in[p] + 256 * in[p + 1]; p += 2; NLEN = in[p] + 256 * in[p + 1]; p += 2; /*check if 16-bit NLEN is really the one's complement of LEN*/ if(LEN + NLEN != 65535) return 21; /*error: NLEN is not one's complement of LEN*/ if((*pos) + LEN >= out->size) { if(!ucvector_resize(out, (*pos) + LEN)) return 9915; } /*read the literal data: LEN bytes are now stored in the out buffer*/ if(p + LEN > inlength) return 23; /*error: reading outside of in buffer*/ for(n = 0; n < LEN; n++) out->data[(*pos)++] = in[p++]; (*bp) = p * 8; return error; } /*inflate the deflated data (cfr. deflate spec); return value is the error*/ unsigned LodeFlate_inflate(ucvector* out, const unsigned char* in, size_t insize, size_t inpos) { size_t bp = 0; /*bit pointer in the "in" data, current byte is bp >> 3, current bit is bp & 0x7 (from lsb to msb of the byte)*/ unsigned BFINAL = 0; size_t pos = 0; /*byte position in the out buffer*/ unsigned error = 0; while(!BFINAL) { unsigned BTYPE; if((bp >> 3) >= insize) return 52; /*error, bit pointer will jump past memory*/ BFINAL = readBitFromStream(&bp, &in[inpos]); BTYPE = 1 * readBitFromStream(&bp, &in[inpos]); BTYPE += 2 * readBitFromStream(&bp, &in[inpos]); if(BTYPE == 3) return 20; /*error: invalid BTYPE*/ else if(BTYPE == 0) error = inflateNoCompression(out, &in[inpos], &bp, &pos, insize); /*no compression*/ else error = inflateHuffmanBlock(out, &in[inpos], &bp, &pos, insize, BTYPE); /*compression, BTYPE 01 or 10*/ if(error) return error; } if(!ucvector_resize(out, pos)) error = 9916; /*Only now we know the true size of out, resize it to that*/ return error; } #endif /*LODEPNG_COMPILE_DECODER*/ #ifdef LODEPNG_COMPILE_ENCODER /* ////////////////////////////////////////////////////////////////////////// */ /* / Deflator / */ /* ////////////////////////////////////////////////////////////////////////// */ static const size_t MAX_SUPPORTED_DEFLATE_LENGTH = 258; /*bitlen is the size in bits of the code*/ static void addHuffmanSymbol(size_t* bp, ucvector* compressed, unsigned code, unsigned bitlen) { addBitsToStreamReversed(bp, compressed, code, bitlen); } /*search the index in the array, that has the largest value smaller than or equal to the given value, given array must be sorted (if no value is smaller, it returns the size of the given array)*/ static size_t searchCodeIndex(const unsigned* array, size_t array_size, size_t value) { /*linear search implementation*/ /*for(size_t i = 1; i < array_size; i++) if(array[i] > value) return i - 1; return array_size - 1;*/ /*binary search implementation (not that much faster) (precondition: array_size > 0)*/ size_t left = 1; size_t right = array_size - 1; while(left <= right) { size_t mid = (left + right) / 2; if(array[mid] <= value) left = mid + 1; /*the value to find is more to the right*/ else if(array[mid - 1] > value) right = mid - 1; /*the value to find is more to the left*/ else return mid - 1; } return array_size - 1; } static void addLengthDistance(uivector* values, size_t length, size_t distance) { /*values in encoded vector are those used by deflate: 0-255: literal bytes 256: end 257-285: length/distance pair (length code, followed by extra length bits, distance code, extra distance bits) 286-287: invalid*/ unsigned length_code = (unsigned)searchCodeIndex(LENGTHBASE, 29, length); unsigned extra_length = (unsigned)(length - LENGTHBASE[length_code]); unsigned dist_code = (unsigned)searchCodeIndex(DISTANCEBASE, 30, distance); unsigned extra_distance = (unsigned)(distance - DISTANCEBASE[dist_code]); uivector_push_back(values, length_code + FIRST_LENGTH_CODE_INDEX); uivector_push_back(values, extra_length); uivector_push_back(values, dist_code); uivector_push_back(values, extra_distance); } #if 0 /*the "brute force" version of the encodeLZ7 algorithm, not used anymore, kept here for reference*/ static void encodeLZ77_brute(uivector* out, const unsigned char* in, size_t size, unsigned windowSize) { size_t pos; /*using pointer instead of vector for input makes it faster when NOT using optimization when compiling; no influence if optimization is used*/ for(pos = 0; pos < size; pos++) { size_t length = 0, offset = 0; /*the length and offset found for the current position*/ size_t max_offset = pos < windowSize ? pos : windowSize; /*how far back to test*/ size_t current_offset; /**search for the longest string**/ for(current_offset = 1; current_offset < max_offset; current_offset++) /*search backwards through all possible distances (=offsets)*/ { size_t backpos = pos - current_offset; if(in[backpos] == in[pos]) { /*test the next characters*/ size_t current_length = 1; size_t backtest = backpos + 1; size_t foretest = pos + 1; while(foretest < size && in[backtest] == in[foretest] && current_length < MAX_SUPPORTED_DEFLATE_LENGTH) /*maximum supporte length by deflate is max length*/ { if(backpos >= pos) backpos -= current_offset; /*continue as if we work on the decoded bytes after pos by jumping back before pos*/ current_length++; backtest++; foretest++; } if(current_length > length) { length = current_length; /*the longest length*/ offset = current_offset; /*the offset that is related to this longest length*/ if(current_length == MAX_SUPPORTED_DEFLATE_LENGTH) break; /*you can jump out of this for loop once a length of max length is found (gives significant speed gain)*/ } } } /**encode it as length/distance pair or literal value**/ if(length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/ { uivector_push_back(out, in[pos]); } else { addLengthDistance(out, length, offset); pos += (length - 1); } } /*end of the loop through each character of input*/ } #endif static const unsigned HASH_NUM_VALUES = 65536; static const unsigned HASH_NUM_CHARACTERS = 6; static const unsigned HASH_SHIFT = 2; /* Good and fast values: HASH_NUM_VALUES=65536, HASH_NUM_CHARACTERS=6, HASH_SHIFT=2 making HASH_NUM_CHARACTERS larger (like 8), makes the file size larger but is a bit faster making HASH_NUM_CHARACTERS smaller (like 3), makes the file size smaller but is slower */ static unsigned getHash(const unsigned char* data, size_t size, size_t pos) { unsigned result = 0; size_t amount, i; if(pos >= size) return 0; amount = HASH_NUM_CHARACTERS; if(pos + amount >= size) amount = size - pos; for(i = 0; i < amount; i++) result ^= (data[pos + i] << (i * HASH_SHIFT)); return result % HASH_NUM_VALUES; } /*LZ77-encode the data using a hash table technique to let it encode faster. Return value is error code*/ static unsigned encodeLZ77(uivector* out, const unsigned char* in, size_t size, unsigned windowSize) { /**generate hash table**/ vector table; /*HASH_NUM_VALUES uivectors; this represents what would be an std::vector > in C++*/ uivector tablepos1, tablepos2; unsigned pos, i, error = 0; vector_init(&table, sizeof(uivector)); if(!vector_resize(&table, HASH_NUM_VALUES)) return 9917; for(i = 0; i < HASH_NUM_VALUES; i++) { uivector* v = (uivector*)vector_get(&table, i); uivector_init(v); } /*remember start and end positions in the tables to searching in*/ uivector_init(&tablepos1); uivector_init(&tablepos2); if(!uivector_resizev(&tablepos1, HASH_NUM_VALUES, 0)) error = 9918; if(!uivector_resizev(&tablepos2, HASH_NUM_VALUES, 0)) error = 9919; if(!error) { for(pos = 0; pos < size; pos++) { unsigned length = 0, offset = 0; /*the length and offset found for the current position*/ unsigned max_offset = pos < windowSize ? pos : windowSize; /*how far back to test*/ unsigned tablepos; /*/search for the longest string*/ /*first find out where in the table to start (the first value that is in the range from "pos - max_offset" to "pos")*/ unsigned hash = getHash(in, size, pos); if(!uivector_push_back((uivector*)vector_get(&table, hash), pos)) { error = 9920; break; } while(((uivector*)vector_get(&table, hash))->data[tablepos1.data[hash]] < pos - max_offset) tablepos1.data[hash]++; /*it now points to the first value in the table for which the index is larger than or equal to pos - max_offset*/ while(((uivector*)vector_get(&table, hash))->data[tablepos2.data[hash]] < pos) tablepos2.data[hash]++; /*it now points to the first value in the table for which the index is larger than or equal to pos*/ for(tablepos = tablepos2.data[hash] - 1; tablepos >= tablepos1.data[hash] && tablepos < tablepos2.data[hash]; tablepos--) { unsigned backpos = ((uivector*)vector_get(&table, hash))->data[tablepos]; unsigned current_offset = pos - backpos; /*test the next characters*/ unsigned current_length = 0; unsigned backtest = backpos; unsigned foretest = pos; while(foretest < size && in[backtest] == in[foretest] && current_length < MAX_SUPPORTED_DEFLATE_LENGTH) /*maximum supporte length by deflate is max length*/ { if(backpos >= pos) backpos -= current_offset; /*continue as if we work on the decoded bytes after pos by jumping back before pos*/ current_length++; backtest++; foretest++; } if(current_length > length) { length = current_length; /*the longest length*/ offset = current_offset; /*the offset that is related to this longest length*/ if(current_length == MAX_SUPPORTED_DEFLATE_LENGTH) break; /*you can jump out of this for loop once a length of max length is found (gives significant speed gain)*/ } } /**encode it as length/distance pair or literal value**/ if(length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/ { if(!uivector_push_back(out, in[pos])) { error = 9921; break; } } else { unsigned j; addLengthDistance(out, length, offset); for(j = 0; j < length - 1; j++) { pos++; if(!uivector_push_back((uivector*)vector_get(&table, getHash(in, size, pos)), pos)) { error = 9922; break; } } } } /*end of the loop through each character of input*/ } /*end of "if(!error)"*/ /*cleanup*/ for(i = 0; i < table.size; i++) { uivector* v = (uivector*)vector_get(&table, i); uivector_cleanup(v); } vector_cleanup(&table); uivector_cleanup(&tablepos1); uivector_cleanup(&tablepos2); return error; } /* /////////////////////////////////////////////////////////////////////////// */ static unsigned deflateNoCompression(ucvector* out, const unsigned char* data, size_t datasize) { /*non compressed deflate block data: 1 bit BFINAL,2 bits BTYPE,(5 bits): it jumps to start of next byte, 2 bytes LEN, 2 bytes NLEN, LEN bytes literal DATA*/ size_t i, j, numdeflateblocks = datasize / 65536 + 1; unsigned datapos = 0; for(i = 0; i < numdeflateblocks; i++) { unsigned BFINAL, BTYPE, LEN, NLEN; unsigned char firstbyte; BFINAL = (i == numdeflateblocks - 1); BTYPE = 0; firstbyte = (unsigned char)(BFINAL + ((BTYPE & 1) << 1) + ((BTYPE & 2) << 1)); ucvector_push_back(out, firstbyte); LEN = 65535; if(datasize - datapos < 65535) LEN = (unsigned)datasize - datapos; NLEN = 65535 - LEN; ucvector_push_back(out, (unsigned char)(LEN % 256)); ucvector_push_back(out, (unsigned char)(LEN / 256)); ucvector_push_back(out, (unsigned char)(NLEN % 256)); ucvector_push_back(out, (unsigned char)(NLEN / 256)); /*Decompressed data*/ for(j = 0; j < 65535 && datapos < datasize; j++) { ucvector_push_back(out, data[datapos++]); } } return 0; } /*write the encoded data, using lit/len as well as distance codes*/ static void writeLZ77data(size_t* bp, ucvector* out, const uivector* lz77_encoded, const HuffmanTree* codes, const HuffmanTree* codesD) { size_t i = 0; for(i = 0; i < lz77_encoded->size; i++) { unsigned val = lz77_encoded->data[i]; addHuffmanSymbol(bp, out, HuffmanTree_getCode(codes, val), HuffmanTree_getLength(codes, val)); if(val > 256) /*for a length code, 3 more things have to be added*/ { unsigned length_index = val - FIRST_LENGTH_CODE_INDEX; unsigned n_length_extra_bits = LENGTHEXTRA[length_index]; unsigned length_extra_bits = lz77_encoded->data[++i]; unsigned distance_code = lz77_encoded->data[++i]; unsigned distance_index = distance_code; unsigned n_distance_extra_bits = DISTANCEEXTRA[distance_index]; unsigned distance_extra_bits = lz77_encoded->data[++i]; addBitsToStream(bp, out, length_extra_bits, n_length_extra_bits); addHuffmanSymbol(bp, out, HuffmanTree_getCode(codesD, distance_code), HuffmanTree_getLength(codesD, distance_code)); addBitsToStream(bp, out, distance_extra_bits, n_distance_extra_bits); } } } static unsigned deflateDynamic(ucvector* out, const unsigned char* data, size_t datasize, const LodeZlib_DeflateSettings* settings) { /* after the BFINAL and BTYPE, the dynamic block consists out of the following: - 5 bits HLIT, 5 bits HDIST, 4 bits HCLEN - (HCLEN+4)*3 bits code lengths of code length alphabet - HLIT + 257 code lenghts of lit/length alphabet (encoded using the code length alphabet, + possible repetition codes 16, 17, 18) - HDIST + 1 code lengths of distance alphabet (encoded using the code length alphabet, + possible repetition codes 16, 17, 18) - compressed data - 256 (end code) */ unsigned error = 0; uivector lz77_encoded; HuffmanTree codes; /*tree for literal values and length codes*/ HuffmanTree codesD; /*tree for distance codes*/ HuffmanTree codelengthcodes; uivector frequencies; uivector frequenciesD; uivector amounts; /*the amounts in the "normal" order*/ uivector lldl; uivector lldll; /*lit/len & dist code lenghts*/ uivector clcls; unsigned BFINAL = 1; /*make only one block... the first and final one*/ size_t numcodes, numcodesD, i, bp = 0; /*the bit pointer*/ unsigned HLIT, HDIST, HCLEN; uivector_init(&lz77_encoded); HuffmanTree_init(&codes); HuffmanTree_init(&codesD); HuffmanTree_init(&codelengthcodes); uivector_init(&frequencies); uivector_init(&frequenciesD); uivector_init(&amounts); uivector_init(&lldl); uivector_init(&lldll); uivector_init(&clcls); while(!error) /*the goto-avoiding while construct: break out to go to the cleanup phase, a break at the end makes sure the while is never repeated*/ { if(settings->useLZ77) { error = encodeLZ77(&lz77_encoded, data, datasize, settings->windowSize); /*LZ77 encoded*/ if(error) break; } else { if(!uivector_resize(&lz77_encoded, datasize)) { error = 9923; break; } for(i = 0; i < datasize; i++) lz77_encoded.data[i] = data[i]; /*no LZ77, but still will be Huffman compressed*/ } if(!uivector_resizev(&frequencies, 286, 0)) { error = 9924; break; } if(!uivector_resizev(&frequenciesD, 30, 0)) { error = 9925; break; } for(i = 0; i < lz77_encoded.size; i++) { unsigned symbol = lz77_encoded.data[i]; frequencies.data[symbol]++; if(symbol > 256) { unsigned dist = lz77_encoded.data[i + 2]; frequenciesD.data[dist]++; i += 3; } } frequencies.data[256] = 1; /*there will be exactly 1 end code, at the end of the block*/ error = HuffmanTree_makeFromFrequencies(&codes, frequencies.data, frequencies.size, 15); if(error) break; error = HuffmanTree_makeFromFrequencies(&codesD, frequenciesD.data, frequenciesD.size, 15); if(error) break; addBitToStream(&bp, out, BFINAL); addBitToStream(&bp, out, 0); /*first bit of BTYPE "dynamic"*/ addBitToStream(&bp, out, 1); /*second bit of BTYPE "dynamic"*/ numcodes = codes.numcodes; if(numcodes > 286) numcodes = 286; numcodesD = codesD.numcodes; if(numcodesD > 30) numcodesD = 30; for(i = 0; i < numcodes; i++) uivector_push_back(&lldll, HuffmanTree_getLength(&codes, (unsigned)i)); for(i = 0; i < numcodesD; i++) uivector_push_back(&lldll, HuffmanTree_getLength(&codesD, (unsigned)i)); /*make lldl smaller by using repeat codes 16 (copy length 3-6 times), 17 (3-10 zeroes), 18 (11-138 zeroes)*/ for(i = 0; i < (unsigned)lldll.size; i++) { unsigned j = 0; while(i + j + 1 < (unsigned)lldll.size && lldll.data[i + j + 1] == lldll.data[i]) j++; if(lldll.data[i] == 0 && j >= 2) { j++; /*include the first zero*/ if(j <= 10) { uivector_push_back(&lldl, 17); uivector_push_back(&lldl, j - 3); } else { if(j > 138) j = 138; uivector_push_back(&lldl, 18); uivector_push_back(&lldl, j - 11); } i += (j - 1); } else if(j >= 3) { size_t k; unsigned num = j / 6, rest = j % 6; uivector_push_back(&lldl, lldll.data[i]); for(k = 0; k < num; k++) { uivector_push_back(&lldl, 16); uivector_push_back(&lldl, 6 - 3); } if(rest >= 3) { uivector_push_back(&lldl, 16); uivector_push_back(&lldl, rest - 3); } else j -= rest; i += j; } else uivector_push_back(&lldl, lldll.data[i]); } /*generate huffmantree for the length codes of lit/len and dist codes*/ if(!uivector_resizev(&amounts, 19, 0)) { error = 9926; break; } /*16 possible lengths (0-15) and 3 repeat codes (16, 17 and 18)*/ for(i = 0; i < lldl.size; i++) { amounts.data[lldl.data[i]]++; if(lldl.data[i] >= 16) i++; /*after a repeat code come the bits that specify the amount, those don't need to be in the amounts calculation*/ } error = HuffmanTree_makeFromFrequencies(&codelengthcodes, amounts.data, amounts.size, 7); if(error) break; if(!uivector_resize(&clcls, 19)) { error = 9927; break; } for(i = 0; i < 19; i++) clcls.data[i] = HuffmanTree_getLength(&codelengthcodes, CLCL[i]); /*lenghts of code length tree is in the order as specified by deflate*/ while(clcls.data[clcls.size - 1] == 0 && clcls.size > 4) { if(!uivector_resize(&clcls, clcls.size - 1)) { error = 9928; break; } /*remove zeros at the end, but minimum size must be 4*/ } if(error) break; /*write the HLIT, HDIST and HCLEN values*/ HLIT = (unsigned)(numcodes - 257); HDIST = (unsigned)(numcodesD - 1); HCLEN = (unsigned)clcls.size - 4; addBitsToStream(&bp, out, HLIT, 5); addBitsToStream(&bp, out, HDIST, 5); addBitsToStream(&bp, out, HCLEN, 4); /*write the code lenghts of the code length alphabet*/ for(i = 0; i < HCLEN + 4; i++) addBitsToStream(&bp, out, clcls.data[i], 3); /*write the lenghts of the lit/len AND the dist alphabet*/ for(i = 0; i < lldl.size; i++) { addHuffmanSymbol(&bp, out, HuffmanTree_getCode(&codelengthcodes, lldl.data[i]), HuffmanTree_getLength(&codelengthcodes, lldl.data[i])); /*extra bits of repeat codes*/ if(lldl.data[i] == 16) addBitsToStream(&bp, out, lldl.data[++i], 2); else if(lldl.data[i] == 17) addBitsToStream(&bp, out, lldl.data[++i], 3); else if(lldl.data[i] == 18) addBitsToStream(&bp, out, lldl.data[++i], 7); } /*write the compressed data symbols*/ writeLZ77data(&bp, out, &lz77_encoded, &codes, &codesD); if(HuffmanTree_getLength(&codes, 256) == 0) { error = 64; break; } /*the length of the end code 256 must be larger than 0*/ addHuffmanSymbol(&bp, out, HuffmanTree_getCode(&codes, 256), HuffmanTree_getLength(&codes, 256)); /*end code*/ break; /*end of error-while*/ } /*cleanup*/ uivector_cleanup(&lz77_encoded); HuffmanTree_cleanup(&codes); HuffmanTree_cleanup(&codesD); HuffmanTree_cleanup(&codelengthcodes); uivector_cleanup(&frequencies); uivector_cleanup(&frequenciesD); uivector_cleanup(&amounts); uivector_cleanup(&lldl); uivector_cleanup(&lldll); uivector_cleanup(&clcls); return error; } static unsigned deflateFixed(ucvector* out, const unsigned char* data, size_t datasize, const LodeZlib_DeflateSettings* settings) { HuffmanTree codes; /*tree for literal values and length codes*/ HuffmanTree codesD; /*tree for distance codes*/ unsigned BFINAL = 1; /*make only one block... the first and final one*/ unsigned error = 0; size_t i, bp = 0; /*the bit pointer*/ HuffmanTree_init(&codes); HuffmanTree_init(&codesD); generateFixedTree(&codes); generateDistanceTree(&codesD); addBitToStream(&bp, out, BFINAL); addBitToStream(&bp, out, 1); /*first bit of BTYPE*/ addBitToStream(&bp, out, 0); /*second bit of BTYPE*/ if(settings->useLZ77) /*LZ77 encoded*/ { uivector lz77_encoded; uivector_init(&lz77_encoded); error = encodeLZ77(&lz77_encoded, data, datasize, settings->windowSize); if(!error) writeLZ77data(&bp, out, &lz77_encoded, &codes, &codesD); uivector_cleanup(&lz77_encoded); } else /*no LZ77, but still will be Huffman compressed*/ { for(i = 0; i < datasize; i++) addHuffmanSymbol(&bp, out, HuffmanTree_getCode(&codes, data[i]), HuffmanTree_getLength(&codes, data[i])); } if(!error) addHuffmanSymbol(&bp, out, HuffmanTree_getCode(&codes, 256), HuffmanTree_getLength(&codes, 256)); /*"end" code*/ /*cleanup*/ HuffmanTree_cleanup(&codes); HuffmanTree_cleanup(&codesD); return error; } unsigned LodeFlate_deflate(ucvector* out, const unsigned char* data, size_t datasize, const LodeZlib_DeflateSettings* settings) { unsigned error = 0; if(settings->btype == 0) error = deflateNoCompression(out, data, datasize); else if(settings->btype == 1) error = deflateFixed(out, data, datasize, settings); else if(settings->btype == 2) error = deflateDynamic(out, data, datasize, settings); else error = 61; return error; } #endif /*LODEPNG_COMPILE_DECODER*/ /* ////////////////////////////////////////////////////////////////////////// */ /* / Adler32 */ /* ////////////////////////////////////////////////////////////////////////// */ static unsigned update_adler32(unsigned adler, const unsigned char* data, unsigned len) { unsigned s1 = adler & 0xffff; unsigned s2 = (adler >> 16) & 0xffff; while(len > 0) { /*at least 5550 sums can be done before the sums overflow, saving us from a lot of module divisions*/ unsigned amount = len > 5550 ? 5550 : len; len -= amount; while(amount > 0) { s1 = (s1 + *data++); s2 = (s2 + s1); amount--; } s1 %= 65521; s2 %= 65521; } return (s2 << 16) | s1; } /*Return the adler32 of the bytes data[0..len-1]*/ static unsigned adler32(const unsigned char* data, unsigned len) { return update_adler32(1L, data, len); } /* ////////////////////////////////////////////////////////////////////////// */ /* / Reading and writing single bits and bytes from/to stream for Zlib / */ /* ////////////////////////////////////////////////////////////////////////// */ #ifdef LODEPNG_COMPILE_ENCODER void LodeZlib_add32bitInt(ucvector* buffer, unsigned value) { ucvector_push_back(buffer, (unsigned char)((value >> 24) & 0xff)); ucvector_push_back(buffer, (unsigned char)((value >> 16) & 0xff)); ucvector_push_back(buffer, (unsigned char)((value >> 8) & 0xff)); ucvector_push_back(buffer, (unsigned char)((value ) & 0xff)); } #endif /*LODEPNG_COMPILE_ENCODER*/ unsigned LodeZlib_read32bitInt(const unsigned char* buffer) { return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; } /* ////////////////////////////////////////////////////////////////////////// */ /* / Zlib / */ /* ////////////////////////////////////////////////////////////////////////// */ #ifdef LODEPNG_COMPILE_DECODER unsigned LodeZlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in, size_t insize, const LodeZlib_DecompressSettings* settings) { unsigned error = 0; unsigned CM, CINFO, FDICT; ucvector outv; if(insize < 2) { error = 53; return error; } /*error, size of zlib data too small*/ /*read information from zlib header*/ if((in[0] * 256 + in[1]) % 31 != 0) { error = 24; return error; } /*error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way*/ CM = in[0] & 15; CINFO = (in[0] >> 4) & 15; /*FCHECK = in[1] & 31; //FCHECK is already tested above*/ FDICT = (in[1] >> 5) & 1; /*FLEVEL = (in[1] >> 6) & 3; //not really important, all it does it to give a compiler warning about unused variable, we don't care what encoding setting the encoder used*/ if(CM != 8 || CINFO > 7) { error = 25; return error; } /*error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec*/ if(FDICT != 0) { error = 26; return error; } /*error: the specification of PNG says about the zlib stream: "The additional flags shall not specify a preset dictionary."*/ ucvector_init_buffer(&outv, *out, *outsize); /*ucvector-controlled version of the output buffer, for dynamic array*/ error = LodeFlate_inflate(&outv, in, insize, 2); *out = outv.data; *outsize = outv.size; if(error) return error; if(!settings->ignoreAdler32) { unsigned ADLER32 = LodeZlib_read32bitInt(&in[insize - 4]); unsigned checksum = adler32(outv.data, (unsigned)outv.size); if(checksum != ADLER32) { error = 58; return error; } } return error; } #endif /*LODEPNG_COMPILE_DECODER*/ #ifdef LODEPNG_COMPILE_ENCODER unsigned LodeZlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, size_t insize, const LodeZlib_DeflateSettings* settings) { /*initially, *out must be NULL and outsize 0, if you just give some random *out that's pointing to a non allocated buffer, this'll crash*/ ucvector deflatedata, outv; size_t i; unsigned error; unsigned ADLER32; /*zlib data: 1 byte CMF (CM+CINFO), 1 byte FLG, deflate data, 4 byte ADLER32 checksum of the Decompressed data*/ unsigned CMF = 120; /*0b01111000: CM 8, CINFO 7. With CINFO 7, any window size up to 32768 can be used.*/ unsigned FLEVEL = 0; unsigned FDICT = 0; unsigned CMFFLG = 256 * CMF + FDICT * 32 + FLEVEL * 64; unsigned FCHECK = 31 - CMFFLG % 31; CMFFLG += FCHECK; ucvector_init_buffer(&outv, *out, *outsize); /*ucvector-controlled version of the output buffer, for dynamic array*/ ucvector_push_back(&outv, (unsigned char)(CMFFLG / 256)); ucvector_push_back(&outv, (unsigned char)(CMFFLG % 256)); ucvector_init(&deflatedata); error = LodeFlate_deflate(&deflatedata, in, insize, settings); if(!error) { ADLER32 = adler32(in, (unsigned)insize); for(i = 0; i < deflatedata.size; i++) ucvector_push_back(&outv, deflatedata.data[i]); ucvector_cleanup(&deflatedata); LodeZlib_add32bitInt(&outv, ADLER32); } *out = outv.data; *outsize = outv.size; return error; } #endif /*LODEPNG_COMPILE_ENCODER*/ #endif /*LODEPNG_COMPILE_ZLIB*/ /* ////////////////////////////////////////////////////////////////////////// */ #ifdef LODEPNG_COMPILE_ENCODER void LodeZlib_DeflateSettings_init(LodeZlib_DeflateSettings* settings) { settings->btype = 2; /*compress with dynamic huffman tree (not in the mathematical sense, just not the predefined one)*/ settings->useLZ77 = 1; settings->windowSize = 2048; /*this is a good tradeoff between speed and compression ratio*/ } const LodeZlib_DeflateSettings LodeZlib_defaultDeflateSettings = {2, 1, 2048}; #endif /*LODEPNG_COMPILE_ENCODER*/ #ifdef LODEPNG_COMPILE_DECODER void LodeZlib_DecompressSettings_init(LodeZlib_DecompressSettings* settings) { settings->ignoreAdler32 = 0; } const LodeZlib_DecompressSettings LodeZlib_defaultDecompressSettings = {0}; #endif /*LODEPNG_COMPILE_DECODER*/ /* ////////////////////////////////////////////////////////////////////////// */ /* ////////////////////////////////////////////////////////////////////////// */ /* ////////////////////////////////////////////////////////////////////////// */ /* ////////////////////////////////////////////////////////////////////////// */ /* ////////////////////////////////////////////////////////////////////////// */ /* // End of Zlib related code, now comes the PNG related code that uses it// */ /* ////////////////////////////////////////////////////////////////////////// */ /* ////////////////////////////////////////////////////////////////////////// */ /* ////////////////////////////////////////////////////////////////////////// */ /* ////////////////////////////////////////////////////////////////////////// */ /* ////////////////////////////////////////////////////////////////////////// */ #ifdef LODEPNG_COMPILE_PNG /* The two functions below (LodePNG_decompress and LodePNG_compress) directly call the LodeZlib_decompress and LodeZlib_compress functions. The only purpose of the functions below, is to provide the ability to let LodePNG use a different Zlib encoder by only changing the two functions below, instead of changing it inside the vareous places in the other LodePNG functions. *out must be NULL and *outsize must be 0 initially, and after the function is done, *out must point to the decompressed data, *outsize must be the size of it, and must be the size of the useful data in bytes, not the alloc size. */ #ifdef LODEPNG_COMPILE_DECODER static unsigned LodePNG_decompress(unsigned char** out, size_t* outsize, const unsigned char* in, size_t insize, const LodeZlib_DecompressSettings* settings) { return LodeZlib_decompress(out, outsize, in, insize, settings); } #endif /*LODEPNG_COMPILE_DECODER*/ #ifdef LODEPNG_COMPILE_ENCODER static unsigned LodePNG_compress(unsigned char** out, size_t* outsize, const unsigned char* in, size_t insize, const LodeZlib_DeflateSettings* settings) { return LodeZlib_compress(out, outsize, in, insize, settings); } #endif /*LODEPNG_COMPILE_ENCODER*/ /* ////////////////////////////////////////////////////////////////////////// */ /* / CRC32 / */ /* ////////////////////////////////////////////////////////////////////////// */ static unsigned Crc32_crc_table_computed = 0; static unsigned Crc32_crc_table[256]; /*Make the table for a fast CRC.*/ static void Crc32_make_crc_table(void) { unsigned c, k, n; for(n = 0; n < 256; n++) { c = n; for(k = 0; k < 8; k++) { if(c & 1) c = 0xedb88320L ^ (c >> 1); else c = c >> 1; } Crc32_crc_table[n] = c; } Crc32_crc_table_computed = 1; } /*Update a running CRC with the bytes buf[0..len-1]--the CRC should be initialized to all 1's, and the transmitted value is the 1's complement of the final running CRC (see the crc() routine below).*/ static unsigned Crc32_update_crc(const unsigned char* buf, unsigned crc, size_t len) { unsigned c = crc; size_t n; if(!Crc32_crc_table_computed) Crc32_make_crc_table(); for(n = 0; n < len; n++) { c = Crc32_crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); } return c; } /*Return the CRC of the bytes buf[0..len-1].*/ static unsigned Crc32_crc(const unsigned char* buf, size_t len) { return Crc32_update_crc(buf, 0xffffffffL, len) ^ 0xffffffffL; } /* ////////////////////////////////////////////////////////////////////////// */ /* / Reading and writing single bits and bytes from/to stream for LodePNG / */ /* ////////////////////////////////////////////////////////////////////////// */ static unsigned char readBitFromReversedStream(size_t* bitpointer, const unsigned char* bitstream) { unsigned char result = (unsigned char)((bitstream[(*bitpointer) >> 3] >> (7 - ((*bitpointer) & 0x7))) & 1); (*bitpointer)++; return result; } static unsigned readBitsFromReversedStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) { unsigned result = 0; size_t i; for(i = nbits - 1; i < nbits; i--) result += (unsigned)readBitFromReversedStream(bitpointer, bitstream) << i; return result; } #ifdef LODEPNG_COMPILE_DECODER static void setBitOfReversedStream0(size_t* bitpointer, unsigned char* bitstream, unsigned char bit) { /*the current bit in bitstream must be 0 for this to work*/ if(bit) bitstream[(*bitpointer) >> 3] |= (bit << (7 - ((*bitpointer) & 0x7))); /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/ (*bitpointer)++; } #endif /*LODEPNG_COMPILE_DECODER*/ static void setBitOfReversedStream(size_t* bitpointer, unsigned char* bitstream, unsigned char bit) { /*the current bit in bitstream may be 0 or 1 for this to work*/ if(bit == 0) bitstream[(*bitpointer) >> 3] &= (unsigned char)(~(1 << (7 - ((*bitpointer) & 0x7)))); else bitstream[(*bitpointer) >> 3] |= (1 << (7 - ((*bitpointer) & 0x7))); (*bitpointer)++; } static unsigned LodePNG_read32bitInt(const unsigned char* buffer) { return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; } static void LodePNG_set32bitInt(unsigned char* buffer, unsigned value) /*buffer must have at least 4 allocated bytes available*/ { buffer[0] = (unsigned char)((value >> 24) & 0xff); buffer[1] = (unsigned char)((value >> 16) & 0xff); buffer[2] = (unsigned char)((value >> 8) & 0xff); buffer[3] = (unsigned char)((value ) & 0xff); } #ifdef LODEPNG_COMPILE_ENCODER static void LodePNG_add32bitInt(ucvector* buffer, unsigned value) { ucvector_resize(buffer, buffer->size + 4); LodePNG_set32bitInt(&buffer->data[buffer->size - 4], value); } #endif /*LODEPNG_COMPILE_ENCODER*/ /* ////////////////////////////////////////////////////////////////////////// */ /* / PNG chunks / */ /* ////////////////////////////////////////////////////////////////////////// */ unsigned LodePNG_chunk_length(const unsigned char* chunk) /*get the length of the data of the chunk. Total chunk length has 12 bytes more.*/ { return LodePNG_read32bitInt(&chunk[0]); } void LodePNG_chunk_type(char type[5], const unsigned char* chunk) /*puts the 4-byte type in null terminated string*/ { unsigned i; for(i = 0; i < 4; i++) type[i] = chunk[4 + i]; type[4] = 0; /*null termination char*/ } unsigned char LodePNG_chunk_type_equals(const unsigned char* chunk, const char* type) /*check if the type is the given type*/ { if(strlen(type) != 4) return 0; return (chunk[4] == type[0] && chunk[5] == type[1] && chunk[6] == type[2] && chunk[7] == type[3]); } /*properties of PNG chunks gotten from capitalization of chunk type name, as defined by the standard*/ unsigned char LodePNG_chunk_critical(const unsigned char* chunk) /*0: ancillary chunk, 1: it's one of the critical chunk types*/ { return((chunk[4] & 32) == 0); } unsigned char LodePNG_chunk_private(const unsigned char* chunk) /*0: public, 1: private*/ { return((chunk[6] & 32) != 0); } unsigned char LodePNG_chunk_safetocopy(const unsigned char* chunk) /*0: the chunk is unsafe to copy, 1: the chunk is safe to copy*/ { return((chunk[7] & 32) != 0); } unsigned char* LodePNG_chunk_data(unsigned char* chunk) /*get pointer to the data of the chunk*/ { return &chunk[8]; } const unsigned char* LodePNG_chunk_data_const(const unsigned char* chunk) /*get pointer to the data of the chunk*/ { return &chunk[8]; } unsigned LodePNG_chunk_check_crc(const unsigned char* chunk) /*returns 0 if the crc is correct, error code if it's incorrect*/ { unsigned length = LodePNG_chunk_length(chunk); unsigned CRC = LodePNG_read32bitInt(&chunk[length + 8]); unsigned checksum = Crc32_crc(&chunk[4], length + 4); /*the CRC is taken of the data and the 4 chunk type letters, not the length*/ if(CRC != checksum) return 1; else return 0; } void LodePNG_chunk_generate_crc(unsigned char* chunk) /*generates the correct CRC from the data and puts it in the last 4 bytes of the chunk*/ { unsigned length = LodePNG_chunk_length(chunk); unsigned CRC = Crc32_crc(&chunk[4], length + 4); LodePNG_set32bitInt(chunk + 8 + length, CRC); } unsigned char* LodePNG_chunk_next(unsigned char* chunk) /*don't use on IEND chunk, as there is no next chunk then*/ { unsigned total_chunk_length = LodePNG_chunk_length(chunk) + 12; return &chunk[total_chunk_length]; } const unsigned char* LodePNG_chunk_next_const(const unsigned char* chunk) /*don't use on IEND chunk, as there is no next chunk then*/ { unsigned total_chunk_length = LodePNG_chunk_length(chunk) + 12; return &chunk[total_chunk_length]; } unsigned LodePNG_append_chunk(unsigned char** out, size_t* outlength, const unsigned char* chunk) /*appends chunk that was already created, to the data. Returns error code.*/ { unsigned i; unsigned total_chunk_length = LodePNG_chunk_length(chunk) + 12; unsigned char *chunk_start, *new_buffer; size_t new_length = (*outlength) + total_chunk_length; if(new_length < total_chunk_length || new_length < (*outlength)) return 77; /*integer overflow happened*/ new_buffer = (unsigned char*)realloc(*out, new_length); if(!new_buffer) return 9929; (*out) = new_buffer; (*outlength) = new_length; chunk_start = &(*out)[new_length - total_chunk_length]; for(i = 0; i < total_chunk_length; i++) chunk_start[i] = chunk[i]; return 0; } unsigned LodePNG_create_chunk(unsigned char** out, size_t* outlength, unsigned length, const char* type, const unsigned char* data) /*appends new chunk to out. Returns error code; may change memory address of out buffer*/ { unsigned i; unsigned char *chunk, *new_buffer; size_t new_length = (*outlength) + length + 12; if(new_length < length + 12 || new_length < (*outlength)) return 77; /*integer overflow happened*/ new_buffer = (unsigned char*)realloc(*out, new_length); if(!new_buffer) return 9930; (*out) = new_buffer; (*outlength) = new_length; chunk = &(*out)[(*outlength) - length - 12]; /*1: length*/ LodePNG_set32bitInt(chunk, (unsigned)length); /*2: chunk name (4 letters)*/ chunk[4] = type[0]; chunk[5] = type[1]; chunk[6] = type[2]; chunk[7] = type[3]; /*3: the data*/ for(i = 0; i < length; i++) chunk[8 + i] = data[i]; /*4: CRC (of the chunkname characters and the data)*/ LodePNG_chunk_generate_crc(chunk); return 0; } /* ////////////////////////////////////////////////////////////////////////// */ /* / Color types and such / */ /* ////////////////////////////////////////////////////////////////////////// */ /*return type is a LodePNG error code*/ static unsigned checkColorValidity(unsigned colorType, unsigned bd) /*bd = bitDepth*/ { switch(colorType) { case 0: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; break; /*grey*/ case 2: if(!( bd == 8 || bd == 16)) return 37; break; /*RGB*/ case 3: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 )) return 37; break; /*palette*/ case 4: if(!( bd == 8 || bd == 16)) return 37; break; /*grey + alpha*/ case 6: if(!( bd == 8 || bd == 16)) return 37; break; /*RGBA*/ default: return 31; } return 0; /*allowed color type / bits combination*/ } static unsigned getNumColorChannels(unsigned colorType) { switch(colorType) { case 0: return 1; /*grey*/ case 2: return 3; /*RGB*/ case 3: return 1; /*palette*/ case 4: return 2; /*grey + alpha*/ case 6: return 4; /*RGBA*/ } return 0; /*unexisting color type*/ } static unsigned getBpp(unsigned colorType, unsigned bitDepth) { return getNumColorChannels(colorType) * bitDepth; /*bits per pixel is amount of channels * bits per channel*/ } /* ////////////////////////////////////////////////////////////////////////// */ void LodePNG_InfoColor_init(LodePNG_InfoColor* info) { info->key_defined = 0; info->key_r = info->key_g = info->key_b = 0; info->colorType = 6; info->bitDepth = 8; info->palette = 0; info->palettesize = 0; } void LodePNG_InfoColor_cleanup(LodePNG_InfoColor* info) { LodePNG_InfoColor_clearPalette(info); } void LodePNG_InfoColor_clearPalette(LodePNG_InfoColor* info) { if(info->palette) free(info->palette); info->palettesize = 0; } unsigned LodePNG_InfoColor_addPalette(LodePNG_InfoColor* info, unsigned char r, unsigned char g, unsigned char b, unsigned char a) { unsigned char* data; /*the same resize technique as C++ std::vectors is used, and here it's made so that for a palette with the max of 256 colors, it'll have the exact alloc size*/ if(!(info->palettesize & (info->palettesize - 1))) /*if palettesize is 0 or a power of two*/ { /*allocated data must be at least 4* palettesize (for 4 color bytes)*/ size_t alloc_size = info->palettesize == 0 ? 4 : info->palettesize * 4 * 2; data = (unsigned char*)realloc(info->palette, alloc_size); if(!data) return 9931; else info->palette = data; } info->palette[4 * info->palettesize + 0] = r; info->palette[4 * info->palettesize + 1] = g; info->palette[4 * info->palettesize + 2] = b; info->palette[4 * info->palettesize + 3] = a; info->palettesize++; return 0; } unsigned LodePNG_InfoColor_getBpp(const LodePNG_InfoColor* info) { return getBpp(info->colorType, info->bitDepth); } /*calculate bits per pixel out of colorType and bitDepth*/ unsigned LodePNG_InfoColor_getChannels(const LodePNG_InfoColor* info) { return getNumColorChannels(info->colorType); } unsigned LodePNG_InfoColor_isGreyscaleType(const LodePNG_InfoColor* info) { return info->colorType == 0 || info->colorType == 4; } unsigned LodePNG_InfoColor_isAlphaType(const LodePNG_InfoColor* info) { return (info->colorType & 4) != 0; } unsigned LodePNG_InfoColor_equal(const LodePNG_InfoColor* info1, const LodePNG_InfoColor* info2) { return info1->colorType == info2->colorType && info1->bitDepth == info2->bitDepth; /*palette and color key not compared*/ } #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS void LodePNG_UnknownChunks_init(LodePNG_UnknownChunks* chunks) { unsigned i; for(i = 0; i < 3; i++) chunks->data[i] = 0; for(i = 0; i < 3; i++) chunks->datasize[i] = 0; } void LodePNG_UnknownChunks_cleanup(LodePNG_UnknownChunks* chunks) { unsigned i; for(i = 0; i < 3; i++) free(chunks->data[i]); } unsigned LodePNG_UnknownChunks_copy(LodePNG_UnknownChunks* dest, const LodePNG_UnknownChunks* src) { unsigned i; LodePNG_UnknownChunks_cleanup(dest); for(i = 0; i < 3; i++) { size_t j; dest->datasize[i] = src->datasize[i]; dest->data[i] = (unsigned char*)malloc(src->datasize[i]); if(!dest->data[i] && dest->datasize[i]) return 9932; for(j = 0; j < src->datasize[i]; j++) dest->data[i][j] = src->data[i][j]; } return 0; } #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS void LodePNG_Text_init(LodePNG_Text* text) { text->num = 0; text->keys = NULL; text->strings = NULL; } void LodePNG_Text_cleanup(LodePNG_Text* text) { LodePNG_Text_clear(text); } unsigned LodePNG_Text_copy(LodePNG_Text* dest, const LodePNG_Text* source) { size_t i = 0; dest->keys = 0; dest->strings = 0; dest->num = 0; for(i = 0; i < source->num; i++) { unsigned error = LodePNG_Text_add(dest, source->keys[i], source->strings[i]); if(error) return error; } return 0; } void LodePNG_Text_clear(LodePNG_Text* text) { size_t i; for(i = 0; i < text->num; i++) { string_cleanup(&text->keys[i]); string_cleanup(&text->strings[i]); } free(text->keys); free(text->strings); } unsigned LodePNG_Text_add(LodePNG_Text* text, const char* key, const char* str) { char** new_keys = (char**)(realloc(text->keys, sizeof(char*) * (text->num + 1))); char** new_strings = (char**)(realloc(text->strings, sizeof(char*) * (text->num + 1))); if(!new_keys || !new_strings) { free(new_keys); free(new_strings); return 9933; } text->num++; text->keys = new_keys; text->strings = new_strings; string_init(&text->keys[text->num - 1]); string_set(&text->keys[text->num - 1], key); string_init(&text->strings[text->num - 1]); string_set(&text->strings[text->num - 1], str); return 0; } /******************************************************************************/ void LodePNG_IText_init(LodePNG_IText* text) { text->num = 0; text->keys = NULL; text->langtags = NULL; text->transkeys = NULL; text->strings = NULL; } void LodePNG_IText_cleanup(LodePNG_IText* text) { LodePNG_IText_clear(text); } unsigned LodePNG_IText_copy(LodePNG_IText* dest, const LodePNG_IText* source) { size_t i = 0; dest->keys = 0; dest->langtags = 0; dest->transkeys = 0; dest->strings = 0; dest->num = 0; for(i = 0; i < source->num; i++) { unsigned error = LodePNG_IText_add(dest, source->keys[i], source->langtags[i], source->transkeys[i], source->strings[i]); if(error) return error; } return 0; } void LodePNG_IText_clear(LodePNG_IText* text) { size_t i; for(i = 0; i < text->num; i++) { string_cleanup(&text->keys[i]); string_cleanup(&text->langtags[i]); string_cleanup(&text->transkeys[i]); string_cleanup(&text->strings[i]); } free(text->keys); free(text->langtags); free(text->transkeys); free(text->strings); } unsigned LodePNG_IText_add(LodePNG_IText* text, const char* key, const char* langtag, const char* transkey, const char* str) { char** new_keys = (char**)(realloc(text->keys, sizeof(char*) * (text->num + 1))); char** new_langtags = (char**)(realloc(text->langtags, sizeof(char*) * (text->num + 1))); char** new_transkeys = (char**)(realloc(text->transkeys, sizeof(char*) * (text->num + 1))); char** new_strings = (char**)(realloc(text->strings, sizeof(char*) * (text->num + 1))); if(!new_keys || !new_langtags || !new_transkeys || !new_strings) { free(new_keys); free(new_langtags); free(new_transkeys); free(new_strings); return 9934; } text->num++; text->keys = new_keys; text->langtags = new_langtags; text->transkeys = new_transkeys; text->strings = new_strings; string_init(&text->keys[text->num - 1]); string_set(&text->keys[text->num - 1], key); string_init(&text->langtags[text->num - 1]); string_set(&text->langtags[text->num - 1], langtag); string_init(&text->transkeys[text->num - 1]); string_set(&text->transkeys[text->num - 1], transkey); string_init(&text->strings[text->num - 1]); string_set(&text->strings[text->num - 1], str); return 0; } #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ void LodePNG_InfoPng_init(LodePNG_InfoPng* info) { info->width = info->height = 0; LodePNG_InfoColor_init(&info->color); info->interlaceMethod = 0; info->compressionMethod = 0; info->filterMethod = 0; #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS info->background_defined = 0; info->background_r = info->background_g = info->background_b = 0; LodePNG_Text_init(&info->text); LodePNG_IText_init(&info->itext); info->time_defined = 0; info->phys_defined = 0; #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS LodePNG_UnknownChunks_init(&info->unknown_chunks); #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ } void LodePNG_InfoPng_cleanup(LodePNG_InfoPng* info) { LodePNG_InfoColor_cleanup(&info->color); #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS LodePNG_Text_cleanup(&info->text); LodePNG_IText_cleanup(&info->itext); #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS LodePNG_UnknownChunks_cleanup(&info->unknown_chunks); #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ } unsigned LodePNG_InfoPng_copy(LodePNG_InfoPng* dest, const LodePNG_InfoPng* source) { unsigned error = 0; LodePNG_InfoPng_cleanup(dest); *dest = *source; LodePNG_InfoColor_init(&dest->color); error = LodePNG_InfoColor_copy(&dest->color, &source->color); if(error) return error; #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS error = LodePNG_Text_copy(&dest->text, &source->text); if(error) return error; error = LodePNG_IText_copy(&dest->itext, &source->itext); if(error) return error; #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS LodePNG_UnknownChunks_init(&dest->unknown_chunks); error = LodePNG_UnknownChunks_copy(&dest->unknown_chunks, &source->unknown_chunks); if(error) return error; #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ return error; } void LodePNG_InfoPng_swap(LodePNG_InfoPng* a, LodePNG_InfoPng* b) { LodePNG_InfoPng temp = *a; *a = *b; *b = temp; } unsigned LodePNG_InfoColor_copy(LodePNG_InfoColor* dest, const LodePNG_InfoColor* source) { size_t i; LodePNG_InfoColor_cleanup(dest); *dest = *source; dest->palette = (unsigned char*)malloc(source->palettesize * 4); if(!dest->palette && source->palettesize) return 9935; for(i = 0; i < source->palettesize * 4; i++) dest->palette[i] = source->palette[i]; return 0; } void LodePNG_InfoRaw_init(LodePNG_InfoRaw* info) { LodePNG_InfoColor_init(&info->color); } void LodePNG_InfoRaw_cleanup(LodePNG_InfoRaw* info) { LodePNG_InfoColor_cleanup(&info->color); } unsigned LodePNG_InfoRaw_copy(LodePNG_InfoRaw* dest, const LodePNG_InfoRaw* source) { unsigned error = 0; LodePNG_InfoRaw_cleanup(dest); *dest = *source; LodePNG_InfoColor_init(&dest->color); error = LodePNG_InfoColor_copy(&dest->color, &source->color); if(error) return error; return error; } /* ////////////////////////////////////////////////////////////////////////// */ /* converts from any color type to 24-bit or 32-bit (later maybe more supported). return value = LodePNG error code the out buffer must have (w * h * bpp + 7) / 8 bytes, where bpp is the bits per pixel of the output color type (LodePNG_InfoColor_getBpp) for < 8 bpp images, there may _not_ be padding bits at the end of scanlines. */ unsigned LodePNG_convert(unsigned char* out, const unsigned char* in, LodePNG_InfoColor* infoOut, LodePNG_InfoColor* infoIn, unsigned w, unsigned h) { const size_t numpixels = w * h; /*amount of pixels*/ const unsigned OUT_BYTES = LodePNG_InfoColor_getBpp(infoOut) / 8; /*bytes per pixel in the output image*/ const unsigned OUT_ALPHA = LodePNG_InfoColor_isAlphaType(infoOut); /*use 8-bit alpha channel*/ size_t i, c, bp = 0; /*bitpointer, used by less-than-8-bit color types*/ /*cases where in and out already have the same format*/ if(LodePNG_InfoColor_equal(infoIn, infoOut)) { size_t i, size = (w * h * LodePNG_InfoColor_getBpp(infoIn) + 7) / 8; for(i = 0; i < size; i++) out[i] = in[i]; return 0; } if((infoOut->colorType == 2 || infoOut->colorType == 6) && infoOut->bitDepth == 8) { if(infoIn->bitDepth == 8) { switch(infoIn->colorType) { case 0: /*greyscale color*/ for(i = 0; i < numpixels; i++) { if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; out[OUT_BYTES * i + 0] = out[OUT_BYTES * i + 1] = out[OUT_BYTES * i + 2] = in[i]; if(OUT_ALPHA && infoIn->key_defined && in[i] == infoIn->key_r) out[OUT_BYTES * i + 3] = 0; } break; case 2: /*RGB color*/ for(i = 0; i < numpixels; i++) { if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; for(c = 0; c < 3; c++) out[OUT_BYTES * i + c] = in[3 * i + c]; if(OUT_ALPHA && infoIn->key_defined == 1 && in[3 * i + 0] == infoIn->key_r && in[3 * i + 1] == infoIn->key_g && in[3 * i + 2] == infoIn->key_b) out[OUT_BYTES * i + 3] = 0; } break; case 3: /*indexed color (palette)*/ for(i = 0; i < numpixels; i++) { if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; if(in[i] >= infoIn->palettesize) return 46; for(c = 0; c < OUT_BYTES; c++) out[OUT_BYTES * i + c] = infoIn->palette[4 * in[i] + c]; /*get rgb colors from the palette*/ } break; case 4: /*greyscale with alpha*/ for(i = 0; i < numpixels; i++) { out[OUT_BYTES * i + 0] = out[OUT_BYTES * i + 1] = out[OUT_BYTES * i + 2] = in[2 * i + 0]; if(OUT_ALPHA) out[OUT_BYTES * i + 3] = in[2 * i + 1]; } break; case 6: /*RGB with alpha*/ for(i = 0; i < numpixels; i++) { for(c = 0; c < OUT_BYTES; c++) out[OUT_BYTES * i + c] = in[4 * i + c]; } break; default: break; } } else if(infoIn->bitDepth == 16) { switch(infoIn->colorType) { case 0: /*greyscale color*/ for(i = 0; i < numpixels; i++) { if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; out[OUT_BYTES * i + 0] = out[OUT_BYTES * i + 1] = out[OUT_BYTES * i + 2] = in[2 * i]; if(OUT_ALPHA && infoIn->key_defined && 256U * in[i] + in[i + 1] == infoIn->key_r) out[OUT_BYTES * i + 3] = 0; } break; case 2: /*RGB color*/ for(i = 0; i < numpixels; i++) { if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; for(c = 0; c < 3; c++) out[OUT_BYTES * i + c] = in[6 * i + 2 * c]; if(OUT_ALPHA && infoIn->key_defined && 256U * in[6 * i + 0] + in[6 * i + 1] == infoIn->key_r && 256U * in[6 * i + 2] + in[6 * i + 3] == infoIn->key_g && 256U * in[6 * i + 4] + in[6 * i + 5] == infoIn->key_b) out[OUT_BYTES * i + 3] = 0; } break; case 4: /*greyscale with alpha*/ for(i = 0; i < numpixels; i++) { out[OUT_BYTES * i + 0] = out[OUT_BYTES * i + 1] = out[OUT_BYTES * i + 2] = in[4 * i]; /*most significant byte*/ if(OUT_ALPHA) out[OUT_BYTES * i + 3] = in[4 * i + 2]; } break; case 6: /*RGB with alpha*/ for(i = 0; i < numpixels; i++) { for(c = 0; c < OUT_BYTES; c++) out[OUT_BYTES * i + c] = in[8 * i + 2 * c]; } break; default: break; } } else /*infoIn->bitDepth is less than 8 bit per channel*/ { switch(infoIn->colorType) { case 0: /*greyscale color*/ for(i = 0; i < numpixels; i++) { unsigned value = readBitsFromReversedStream(&bp, in, infoIn->bitDepth); if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; if(OUT_ALPHA && infoIn->key_defined && value && ((1U << infoIn->bitDepth) - 1U) == infoIn->key_r && ((1U << infoIn->bitDepth) - 1U)) out[OUT_BYTES * i + 3] = 0; value = (value * 255) / ((1 << infoIn->bitDepth) - 1); /*scale value from 0 to 255*/ out[OUT_BYTES * i + 0] = out[OUT_BYTES * i + 1] = out[OUT_BYTES * i + 2] = (unsigned char)(value); } break; case 3: /*indexed color (palette)*/ for(i = 0; i < numpixels; i++) { unsigned value = readBitsFromReversedStream(&bp, in, infoIn->bitDepth); if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; if(value >= infoIn->palettesize) return 47; for(c = 0; c < OUT_BYTES; c++) out[OUT_BYTES * i + c] = infoIn->palette[4 * value + c]; /*get rgb colors from the palette*/ } break; default: break; } } } else if(LodePNG_InfoColor_isGreyscaleType(infoOut) && infoOut->bitDepth == 8) /*conversion from greyscale to greyscale*/ { if(!LodePNG_InfoColor_isGreyscaleType(infoIn)) return 62; if(infoIn->bitDepth == 8) { switch(infoIn->colorType) { case 0: /*greyscale color*/ for(i = 0; i < numpixels; i++) { if(OUT_ALPHA) out[OUT_BYTES * i + 1] = 255; out[OUT_BYTES * i] = in[i]; if(OUT_ALPHA && infoIn->key_defined && in[i] == infoIn->key_r) out[OUT_BYTES * i + 1] = 0; } break; case 4: /*greyscale with alpha*/ for(i = 0; i < numpixels; i++) { out[OUT_BYTES * i + 0] = in[2 * i + 0]; if(OUT_ALPHA) out[OUT_BYTES * i + 1] = in[2 * i + 1]; } break; default: return 31; } } else if(infoIn->bitDepth == 16) { switch(infoIn->colorType) { case 0: /*greyscale color*/ for(i = 0; i < numpixels; i++) { if(OUT_ALPHA) out[OUT_BYTES * i + 1] = 255; out[OUT_BYTES * i] = in[2 * i]; if(OUT_ALPHA && infoIn->key_defined && 256U * in[i] + in[i + 1] == infoIn->key_r) out[OUT_BYTES * i + 1] = 0; } break; case 4: /*greyscale with alpha*/ for(i = 0; i < numpixels; i++) { out[OUT_BYTES * i] = in[4 * i]; /*most significant byte*/ if(OUT_ALPHA) out[OUT_BYTES * i + 1] = in[4 * i + 2]; /*most significant byte*/ } break; default: return 31; } } else /*infoIn->bitDepth is less than 8 bit per channel*/ { if(infoIn->colorType != 0) return 31; /*colorType 0 is the only greyscale type with < 8 bits per channel*/ for(i = 0; i < numpixels; i++) { unsigned value = readBitsFromReversedStream(&bp, in, infoIn->bitDepth); if(OUT_ALPHA) out[OUT_BYTES * i + 1] = 255; if(OUT_ALPHA && infoIn->key_defined && value && ((1U << infoIn->bitDepth) - 1U) == infoIn->key_r && ((1U << infoIn->bitDepth) - 1U)) out[OUT_BYTES * i + 1] = 0; value = (value * 255) / ((1 << infoIn->bitDepth) - 1); /*scale value from 0 to 255*/ out[OUT_BYTES * i] = (unsigned char)(value); } } } else return 59; return 0; } /*Paeth predicter, used by PNG filter type 4*/ static int paethPredictor(int a, int b, int c) { int p = a + b - c; int pa = p > a ? p - a : a - p; int pb = p > b ? p - b : b - p; int pc = p > c ? p - c : c - p; if(pa <= pb && pa <= pc) return a; else if(pb <= pc) return b; else return c; } /*shared values used by multiple Adam7 related functions*/ static const unsigned ADAM7_IX[7] = { 0, 4, 0, 2, 0, 1, 0 }; /*x start values*/ static const unsigned ADAM7_IY[7] = { 0, 0, 4, 0, 2, 0, 1 }; /*y start values*/ static const unsigned ADAM7_DX[7] = { 8, 8, 4, 4, 2, 2, 1 }; /*x delta values*/ static const unsigned ADAM7_DY[7] = { 8, 8, 8, 4, 4, 2, 2 }; /*y delta values*/ static void Adam7_getpassvalues(unsigned passw[7], unsigned passh[7], size_t filter_passstart[8], size_t padded_passstart[8], size_t passstart[8], unsigned w, unsigned h, unsigned bpp) { /*the passstart values have 8 values: the 8th one actually indicates the byte after the end of the 7th (= last) pass*/ unsigned i; /*calculate width and height in pixels of each pass*/ for(i = 0; i < 7; i++) { passw[i] = (w + ADAM7_DX[i] - ADAM7_IX[i] - 1) / ADAM7_DX[i]; passh[i] = (h + ADAM7_DY[i] - ADAM7_IY[i] - 1) / ADAM7_DY[i]; if(passw[i] == 0) passh[i] = 0; if(passh[i] == 0) passw[i] = 0; } filter_passstart[0] = padded_passstart[0] = passstart[0] = 0; for(i = 0; i < 7; i++) { filter_passstart[i + 1] = filter_passstart[i] + ((passw[i] && passh[i]) ? passh[i] * (1 + (passw[i] * bpp + 7) / 8) : 0); /*if passw[i] is 0, it's 0 bytes, not 1 (no filtertype-byte)*/ padded_passstart[i + 1] = padded_passstart[i] + passh[i] * ((passw[i] * bpp + 7) / 8); /*bits padded if needed to fill full byte at end of each scanline*/ passstart[i + 1] = passstart[i] + (passh[i] * passw[i] * bpp + 7) / 8; /*only padded at end of reduced image*/ } } #ifdef LODEPNG_COMPILE_DECODER /* ////////////////////////////////////////////////////////////////////////// */ /* / PNG Decoder / */ /* ////////////////////////////////////////////////////////////////////////// */ /*read the information from the header and store it in the LodePNG_Info. return value is error*/ void LodePNG_inspect(LodePNG_Decoder* decoder, const unsigned char* in, size_t inlength) { if(inlength == 0 || in == 0) { decoder->error = 48; return; } /*the given data is empty*/ if(inlength < 29) { decoder->error = 27; return; } /*error: the data length is smaller than the length of the header*/ /*when decoding a new PNG image, make sure all parameters created after previous decoding are reset*/ LodePNG_InfoPng_cleanup(&decoder->infoPng); LodePNG_InfoPng_init(&decoder->infoPng); decoder->error = 0; if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) { decoder->error = 28; return; } /*error: the first 8 bytes are not the correct PNG signature*/ if(in[12] != 'I' || in[13] != 'H' || in[14] != 'D' || in[15] != 'R') { decoder->error = 29; return; } /*error: it doesn't start with a IHDR chunk!*/ /*read the values given in the header*/ decoder->infoPng.width = LodePNG_read32bitInt(&in[16]); decoder->infoPng.height = LodePNG_read32bitInt(&in[20]); decoder->infoPng.color.bitDepth = in[24]; decoder->infoPng.color.colorType = in[25]; decoder->infoPng.compressionMethod = in[26]; decoder->infoPng.filterMethod = in[27]; decoder->infoPng.interlaceMethod = in[28]; if(!decoder->settings.ignoreCrc) { unsigned CRC = LodePNG_read32bitInt(&in[29]); unsigned checksum = Crc32_crc(&in[12], 17); if(CRC != checksum) { decoder->error = 57; return; } } if(decoder->infoPng.compressionMethod != 0) { decoder->error = 32; return; } /*error: only compression method 0 is allowed in the specification*/ if(decoder->infoPng.filterMethod != 0) { decoder->error = 33; return; } /*error: only filter method 0 is allowed in the specification*/ if(decoder->infoPng.interlaceMethod > 1) { decoder->error = 34; return; } /*error: only interlace methods 0 and 1 exist in the specification*/ decoder->error = checkColorValidity(decoder->infoPng.color.colorType, decoder->infoPng.color.bitDepth); } static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, size_t bytewidth, unsigned char filterType, size_t length) { /* For PNG filter method 0 unfilter a PNG image scanline by scanline. when the pixels are smaller than 1 byte, the filter works byte per byte (bytewidth = 1) precon is the previous unfiltered scanline, recon the result, scanline the current one the incoming scanlines do NOT include the filtertype byte, that one is given in the parameter filterType instead recon and scanline MAY be the same memory address! precon must be disjoint. */ size_t i; switch(filterType) { case 0: for(i = 0; i < length; i++) recon[i] = scanline[i]; break; case 1: for(i = 0; i < bytewidth; i++) recon[i] = scanline[i]; for(i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth]; break; case 2: if(precon) for(i = 0; i < length; i++) recon[i] = scanline[i] + precon[i]; else for(i = 0; i < length; i++) recon[i] = scanline[i]; break; case 3: if(precon) { for(i = 0; i < bytewidth; i++) recon[i] = scanline[i] + precon[i] / 2; for(i = bytewidth; i < length; i++) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2); } else { for(i = 0; i < bytewidth; i++) recon[i] = scanline[i]; for(i = bytewidth; i < length; i++) recon[i] = scanline[i] + recon[i - bytewidth] / 2; } break; case 4: if(precon) { for(i = 0; i < bytewidth; i++) recon[i] = (unsigned char)(scanline[i] + paethPredictor(0, precon[i], 0)); for(i = bytewidth; i < length; i++) recon[i] = (unsigned char)(scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth])); } else { for(i = 0; i < bytewidth; i++) recon[i] = scanline[i]; for(i = bytewidth; i < length; i++) recon[i] = (unsigned char)(scanline[i] + paethPredictor(recon[i - bytewidth], 0, 0)); } break; default: return 36; /*error: unexisting filter type given*/ } return 0; } static unsigned unfilter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) { /* For PNG filter method 0 this function unfilters a single image (e.g. without interlacing this is called once, with Adam7 it's called 7 times) out must have enough bytes allocated already, in must have the scanlines + 1 filtertype byte per scanline w and h are image dimensions or dimensions of reduced image, bpp is bits per pixel in and out are allowed to be the same memory address! */ unsigned y; unsigned char* prevline = 0; size_t bytewidth = (bpp + 7) / 8; /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ size_t linebytes = (w * bpp + 7) / 8; for(y = 0; y < h; y++) { size_t outindex = linebytes * y; size_t inindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ unsigned char filterType = in[inindex]; unsigned error = unfilterScanline(&out[outindex], &in[inindex + 1], prevline, bytewidth, filterType, linebytes); if(error) return error; prevline = &out[outindex]; } return 0; } static void Adam7_deinterlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) { /*Note: this function works on image buffers WITHOUT padding bits at end of scanlines with non-multiple-of-8 bit amounts, only between reduced images is padding out must be big enough AND must be 0 everywhere if bpp < 8 in the current implementation (because that's likely a little bit faster)*/ unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8]; unsigned i; Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); if(bpp >= 8) { for(i = 0; i < 7; i++) { unsigned x, y, b; size_t bytewidth = bpp / 8; for(y = 0; y < passh[i]; y++) for(x = 0; x < passw[i]; x++) { size_t pixelinstart = passstart[i] + (y * passw[i] + x) * bytewidth; size_t pixeloutstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth; for(b = 0; b < bytewidth; b++) { out[pixeloutstart + b] = in[pixelinstart + b]; } } } } else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ { for(i = 0; i < 7; i++) { unsigned x, y, b; unsigned ilinebits = bpp * passw[i]; unsigned olinebits = bpp * w; size_t obp, ibp; /*bit pointers (for out and in buffer)*/ for(y = 0; y < passh[i]; y++) for(x = 0; x < passw[i]; x++) { ibp = (8 * passstart[i]) + (y * ilinebits + x * bpp); obp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp; for(b = 0; b < bpp; b++) { unsigned char bit = readBitFromReversedStream(&ibp, in); setBitOfReversedStream0(&obp, out, bit); /*note that this function assumes the out buffer is completely 0, use setBitOfReversedStream otherwise*/ } } } } } static void removePaddingBits(unsigned char* out, const unsigned char* in, size_t olinebits, size_t ilinebits, unsigned h) { /* After filtering there are still padding bits if scanlines have non multiple of 8 bit amounts. They need to be removed (except at last scanline of (Adam7-reduced) image) before working with pure image buffers for the Adam7 code, the color convert code and the output to the user. in and out are allowed to be the same buffer, in may also be higher but still overlapping; in must have >= ilinebits*h bits, out must have >= olinebits*h bits, olinebits must be <= ilinebits also used to move bits after earlier such operations happened, e.g. in a sequence of reduced images from Adam7 only useful if (ilinebits - olinebits) is a value in the range 1..7 */ unsigned y; size_t diff = ilinebits - olinebits; size_t obp = 0, ibp = 0; /*bit pointers*/ for(y = 0; y < h; y++) { size_t x; for(x = 0; x < olinebits; x++) { unsigned char bit = readBitFromReversedStream(&ibp, in); setBitOfReversedStream(&obp, out, bit); } ibp += diff; } } /*out must be buffer big enough to contain full image, and in must contain the full decompressed data from the IDAT chunks*/ static unsigned postProcessScanlines(unsigned char* out, unsigned char* in, const LodePNG_InfoPng* infoPng) /*return value is error*/ { /* This function converts the filtered-padded-interlaced data into pure 2D image buffer with the PNG's colortype. Steps: *) if no Adam7: 1) unfilter 2) remove padding bits (= posible extra bits per scanline if bpp < 8) *) if adam7: 1) 7x unfilter 2) 7x remove padding bits 3) Adam7_deinterlace NOTE: the in buffer will be overwritten with intermediate data! */ unsigned bpp = LodePNG_InfoColor_getBpp(&infoPng->color); unsigned w = infoPng->width; unsigned h = infoPng->height; unsigned error = 0; if(bpp == 0) return 31; /*error: invalid colortype*/ if(infoPng->interlaceMethod == 0) { if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8) { error = unfilter(in, in, w, h, bpp); if(error) return error; removePaddingBits(out, in, w * bpp, ((w * bpp + 7) / 8) * 8, h); } else error = unfilter(out, in, w, h, bpp); /*we can immediatly filter into the out buffer, no other steps needed*/ } else /*interlaceMethod is 1 (Adam7)*/ { unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8]; unsigned i; Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); for(i = 0; i < 7; i++) { error = unfilter(&in[padded_passstart[i]], &in[filter_passstart[i]], passw[i], passh[i], bpp); if(error) return error; if(bpp < 8) /*TODO: possible efficiency improvement: if in this reduced image the bits fit nicely in 1 scanline, move bytes instead of bits or move not at all*/ { /*remove padding bits in scanlines; after this there still may be padding bits between the different reduced images: each reduced image still starts nicely at a byte*/ removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], passw[i] * bpp, ((passw[i] * bpp + 7) / 8) * 8, passh[i]); } } Adam7_deinterlace(out, in, w, h, bpp); } return error; } /*read a PNG, the result will be in the same color type as the PNG (hence "generic")*/ static void decodeGeneric(LodePNG_Decoder* decoder, unsigned char** out, size_t* outsize, const unsigned char* in, size_t size) { unsigned char IEND = 0; const unsigned char* chunk; size_t i; ucvector idat; /*the data from idat chunks*/ /*for unknown chunk order*/ unsigned unknown = 0; unsigned critical_pos = 1; /*1 = after IHDR, 2 = after PLTE, 3 = after IDAT*/ /*provide some proper output values if error will happen*/ *out = 0; *outsize = 0; if(size == 0 || in == 0) { decoder->error = 48; return; } /*the given data is empty*/ LodePNG_inspect(decoder, in, size); /*reads header and resets other parameters in decoder->infoPng*/ if(decoder->error) return; ucvector_init(&idat); chunk = &in[33]; /*first byte of the first chunk after the header*/ while(!IEND) /*loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. IDAT data is put at the start of the in buffer*/ { unsigned chunkLength; const unsigned char* data; /*the data in the chunk*/ if((size_t)((chunk - in) + 12) > size || chunk < in) { decoder->error = 30; break; } /*error: size of the in buffer too small to contain next chunk*/ chunkLength = LodePNG_chunk_length(chunk); /*length of the data of the chunk, excluding the length bytes, chunk type and CRC bytes*/ if(chunkLength > 2147483647) { decoder->error = 63; break; } if((size_t)((chunk - in) + chunkLength + 12) > size || (chunk + chunkLength + 12) < in) { decoder->error = 35; break; } /*error: size of the in buffer too small to contain next chunk*/ data = LodePNG_chunk_data_const(chunk); /*IDAT chunk, containing compressed image data*/ if(LodePNG_chunk_type_equals(chunk, "IDAT")) { size_t oldsize = idat.size; if(!ucvector_resize(&idat, oldsize + chunkLength)) { decoder->error = 9936; break; } for(i = 0; i < chunkLength; i++) idat.data[oldsize + i] = data[i]; critical_pos = 3; } /*IEND chunk*/ else if(LodePNG_chunk_type_equals(chunk, "IEND")) { IEND = 1; } /*palette chunk (PLTE)*/ else if(LodePNG_chunk_type_equals(chunk, "PLTE")) { unsigned pos = 0; if(decoder->infoPng.color.palette) free(decoder->infoPng.color.palette); decoder->infoPng.color.palettesize = chunkLength / 3; decoder->infoPng.color.palette = (unsigned char*)malloc(4 * decoder->infoPng.color.palettesize); if(!decoder->infoPng.color.palette && decoder->infoPng.color.palettesize) { decoder->error = 9937; break; } if(!decoder->infoPng.color.palette) decoder->infoPng.color.palettesize = 0; /*malloc failed...*/ if(decoder->infoPng.color.palettesize > 256) { decoder->error = 38; break; } /*error: palette too big*/ for(i = 0; i < decoder->infoPng.color.palettesize; i++) { decoder->infoPng.color.palette[4 * i + 0] = data[pos++]; /*R*/ decoder->infoPng.color.palette[4 * i + 1] = data[pos++]; /*G*/ decoder->infoPng.color.palette[4 * i + 2] = data[pos++]; /*B*/ decoder->infoPng.color.palette[4 * i + 3] = 255; /*alpha*/ } critical_pos = 2; } /*palette transparency chunk (tRNS)*/ else if(LodePNG_chunk_type_equals(chunk, "tRNS")) { if(decoder->infoPng.color.colorType == 3) { if(chunkLength > decoder->infoPng.color.palettesize) { decoder->error = 39; break; } /*error: more alpha values given than there are palette entries*/ for(i = 0; i < chunkLength; i++) decoder->infoPng.color.palette[4 * i + 3] = data[i]; } else if(decoder->infoPng.color.colorType == 0) { if(chunkLength != 2) { decoder->error = 40; break; } /*error: this chunk must be 2 bytes for greyscale image*/ decoder->infoPng.color.key_defined = 1; decoder->infoPng.color.key_r = decoder->infoPng.color.key_g = decoder->infoPng.color.key_b = 256 * data[0] + data[1]; } else if(decoder->infoPng.color.colorType == 2) { if(chunkLength != 6) { decoder->error = 41; break; } /*error: this chunk must be 6 bytes for RGB image*/ decoder->infoPng.color.key_defined = 1; decoder->infoPng.color.key_r = 256 * data[0] + data[1]; decoder->infoPng.color.key_g = 256 * data[2] + data[3]; decoder->infoPng.color.key_b = 256 * data[4] + data[5]; } else { decoder->error = 42; break; } /*error: tRNS chunk not allowed for other color models*/ } #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS /*background color chunk (bKGD)*/ else if(LodePNG_chunk_type_equals(chunk, "bKGD")) { if(decoder->infoPng.color.colorType == 3) { if(chunkLength != 1) { decoder->error = 43; break; } /*error: this chunk must be 1 byte for indexed color image*/ decoder->infoPng.background_defined = 1; decoder->infoPng.background_r = decoder->infoPng.background_g = decoder->infoPng.background_g = data[0]; } else if(decoder->infoPng.color.colorType == 0 || decoder->infoPng.color.colorType == 4) { if(chunkLength != 2) { decoder->error = 44; break; } /*error: this chunk must be 2 bytes for greyscale image*/ decoder->infoPng.background_defined = 1; decoder->infoPng.background_r = decoder->infoPng.background_g = decoder->infoPng.background_b = 256 * data[0] + data[1]; } else if(decoder->infoPng.color.colorType == 2 || decoder->infoPng.color.colorType == 6) { if(chunkLength != 6) { decoder->error = 45; break; } /*error: this chunk must be 6 bytes for greyscale image*/ decoder->infoPng.background_defined = 1; decoder->infoPng.background_r = 256 * data[0] + data[1]; decoder->infoPng.background_g = 256 * data[2] + data[3]; decoder->infoPng.background_b = 256 * data[4] + data[5]; } } /*text chunk (tEXt)*/ else if(LodePNG_chunk_type_equals(chunk, "tEXt")) { if(decoder->settings.readTextChunks) { char *key = 0, *str = 0; while(!decoder->error) /*not really a while loop, only used to break on error*/ { unsigned length, string2_begin; for(length = 0; length < chunkLength && data[length] != 0; length++) ; if(length + 1 >= chunkLength) { decoder->error = 75; break; } key = (char*)malloc(length + 1); if(!key) { decoder->error = 9938; break; } key[length] = 0; for(i = 0; i < length; i++) key[i] = data[i]; string2_begin = length + 1; if(string2_begin > chunkLength) { decoder->error = 75; break; } length = chunkLength - string2_begin; str = (char*)malloc(length + 1); if(!str) { decoder->error = 9939; break; } str[length] = 0; for(i = 0; i < length; i++) str[i] = data[string2_begin + i]; decoder->error = LodePNG_Text_add(&decoder->infoPng.text, key, str); break; } free(key); free(str); } } /*compressed text chunk (zTXt)*/ else if(LodePNG_chunk_type_equals(chunk, "zTXt")) { if(decoder->settings.readTextChunks) { unsigned length, string2_begin; char *key = 0; ucvector decoded; ucvector_init(&decoded); while(!decoder->error) /*not really a while loop, only used to break on error*/ { for(length = 0; length < chunkLength && data[length] != 0; length++) ; if(length + 2 >= chunkLength) { decoder->error = 75; break; } key = (char*)malloc(length + 1); if(!key) { decoder->error = 9940; break; } key[length] = 0; for(i = 0; i < length; i++) key[i] = data[i]; if(data[length + 1] != 0) { decoder->error = 72; break; } /*the 0 byte indicating compression must be 0*/ string2_begin = length + 2; if(string2_begin > chunkLength) { decoder->error = 75; break; } length = chunkLength - string2_begin; decoder->error = LodePNG_decompress(&decoded.data, &decoded.size, (unsigned char*)(&data[string2_begin]), length, &decoder->settings.zlibsettings); if(decoder->error) break; ucvector_push_back(&decoded, 0); decoder->error = LodePNG_Text_add(&decoder->infoPng.text, key, (char*)decoded.data); break; } free(key); ucvector_cleanup(&decoded); if(decoder->error) break; } } /*international text chunk (iTXt)*/ else if(LodePNG_chunk_type_equals(chunk, "iTXt")) { if(decoder->settings.readTextChunks) { unsigned length, begin, compressed; char *key = 0, *langtag = 0, *transkey = 0; ucvector decoded; ucvector_init(&decoded); while(!decoder->error) /*not really a while loop, only used to break on error*/ { if(chunkLength < 5) { decoder->error = 76; break; } for(length = 0; length < chunkLength && data[length] != 0; length++) ; if(length + 2 >= chunkLength) { decoder->error = 75; break; } key = (char*)malloc(length + 1); if(!key) { decoder->error = 9941; break; } key[length] = 0; for(i = 0; i < length; i++) key[i] = data[i]; compressed = data[length + 1]; if(data[length + 2] != 0) { decoder->error = 72; break; } /*the 0 byte indicating compression must be 0*/ begin = length + 3; length = 0; for(i = begin; i < chunkLength && data[i] != 0; i++) length++; if(begin + length + 1 >= chunkLength) { decoder->error = 75; break; } langtag = (char*)malloc(length + 1); if(!langtag) { decoder->error = 9942; break; } langtag[length] = 0; for(i = 0; i < length; i++) langtag[i] = data[begin + i]; begin += length + 1; length = 0; for(i = begin; i < chunkLength && data[i] != 0; i++) length++; if(begin + length + 1 >= chunkLength) { decoder->error = 75; break; } transkey = (char*)malloc(length + 1); if(!transkey) { decoder->error = 9943; break; } transkey[length] = 0; for(i = 0; i < length; i++) transkey[i] = data[begin + i]; begin += length + 1; if(begin > chunkLength) { decoder->error = 75; break; } length = chunkLength - begin; if(compressed) { decoder->error = LodePNG_decompress(&decoded.data, &decoded.size, (unsigned char*)(&data[begin]), length, &decoder->settings.zlibsettings); if(decoder->error) break; ucvector_push_back(&decoded, 0); } else { if(!ucvector_resize(&decoded, length + 1)) { decoder->error = 9944; break; } decoded.data[length] = 0; for(i = 0; i < length; i++) decoded.data[i] = data[begin + i]; } decoder->error = LodePNG_IText_add(&decoder->infoPng.itext, key, langtag, transkey, (char*)decoded.data); break; } free(key); free(langtag); free(transkey); ucvector_cleanup(&decoded); if(decoder->error) break; } } else if(LodePNG_chunk_type_equals(chunk, "tIME")) { if(chunkLength != 7) { decoder->error = 73; break; } decoder->infoPng.time_defined = 1; decoder->infoPng.time.year = 256 * data[0] + data[+ 1]; decoder->infoPng.time.month = data[2]; decoder->infoPng.time.day = data[3]; decoder->infoPng.time.hour = data[4]; decoder->infoPng.time.minute = data[5]; decoder->infoPng.time.second = data[6]; } else if(LodePNG_chunk_type_equals(chunk, "pHYs")) { if(chunkLength != 9) { decoder->error = 74; break; } decoder->infoPng.phys_defined = 1; decoder->infoPng.phys_x = 16777216 * data[0] + 65536 * data[1] + 256 * data[2] + data[3]; decoder->infoPng.phys_y = 16777216 * data[4] + 65536 * data[5] + 256 * data[6] + data[7]; decoder->infoPng.phys_unit = data[8]; } #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ else /*it's not an implemented chunk type, so ignore it: skip over the data*/ { if(LodePNG_chunk_critical(chunk)) { decoder->error = 69; break; } /*error: unknown critical chunk (5th bit of first byte of chunk type is 0)*/ unknown = 1; #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS if(decoder->settings.rememberUnknownChunks) { LodePNG_UnknownChunks* unknown = &decoder->infoPng.unknown_chunks; decoder->error = LodePNG_append_chunk(&unknown->data[critical_pos - 1], &unknown->datasize[critical_pos - 1], chunk); if(decoder->error) break; } #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ } if(!decoder->settings.ignoreCrc && !unknown) /*check CRC if wanted, only on known chunk types*/ { if(LodePNG_chunk_check_crc(chunk)) { decoder->error = 57; break; } } if(!IEND) chunk = LodePNG_chunk_next_const(chunk); } if(!decoder->error) { ucvector scanlines; ucvector_init(&scanlines); if(!ucvector_resize(&scanlines, ((decoder->infoPng.width * (decoder->infoPng.height * LodePNG_InfoColor_getBpp(&decoder->infoPng.color) + 7)) / 8) + decoder->infoPng.height)) decoder->error = 9945; /*maximum final image length is already reserved in the vector's length - this is not really necessary*/ if(!decoder->error) decoder->error = LodePNG_decompress(&scanlines.data, &scanlines.size, idat.data, idat.size, &decoder->settings.zlibsettings); /*decompress with the Zlib decompressor*/ if(!decoder->error) { ucvector outv; ucvector_init(&outv); if(!ucvector_resizev(&outv, (decoder->infoPng.height * decoder->infoPng.width * LodePNG_InfoColor_getBpp(&decoder->infoPng.color) + 7) / 8, 0)) decoder->error = 9946; if(!decoder->error) decoder->error = postProcessScanlines(outv.data, scanlines.data, &decoder->infoPng); *out = outv.data; *outsize = outv.size; } ucvector_cleanup(&scanlines); } ucvector_cleanup(&idat); } void LodePNG_decode(LodePNG_Decoder* decoder, unsigned char** out, size_t* outsize, const unsigned char* in, size_t insize) { *out = 0; *outsize = 0; decodeGeneric(decoder, out, outsize, in, insize); if(decoder->error) return; if(!decoder->settings.color_convert || LodePNG_InfoColor_equal(&decoder->infoRaw.color, &decoder->infoPng.color)) { /*same color type, no copying or converting of data needed*/ /*store the infoPng color settings on the infoRaw so that the infoRaw still reflects what colorType the raw image has to the end user*/ if(!decoder->settings.color_convert) { decoder->error = LodePNG_InfoColor_copy(&decoder->infoRaw.color, &decoder->infoPng.color); if(decoder->error) return; } } else { /*color conversion needed; sort of copy of the data*/ unsigned char* data = *out; /*TODO: check if this works according to the statement in the documentation: "The converter can convert from greyscale input color type, to 8-bit greyscale or greyscale with alpha"*/ if(!(decoder->infoRaw.color.colorType == 2 || decoder->infoRaw.color.colorType == 6) && !(decoder->infoRaw.color.bitDepth == 8)) { decoder->error = 56; return; } *outsize = (decoder->infoPng.width * decoder->infoPng.height * LodePNG_InfoColor_getBpp(&decoder->infoRaw.color) + 7) / 8; *out = (unsigned char*)malloc(*outsize); if(!(*out)) { decoder->error = 9947; *outsize = 0; } else decoder->error = LodePNG_convert(*out, data, &decoder->infoRaw.color, &decoder->infoPng.color, decoder->infoPng.width, decoder->infoPng.height); free(data); } } unsigned LodePNG_decode32(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) { unsigned error; size_t dummy_size; LodePNG_Decoder decoder; LodePNG_Decoder_init(&decoder); LodePNG_decode(&decoder, out, &dummy_size, in, insize); error = decoder.error; *w = decoder.infoPng.width; *h = decoder.infoPng.height; LodePNG_Decoder_cleanup(&decoder); return error; } #ifdef LODEPNG_COMPILE_DISK unsigned LodePNG_decode32f(unsigned char** out, unsigned* w, unsigned* h, const char* filename) { unsigned char* buffer; size_t buffersize; unsigned error; error = LodePNG_loadFile(&buffer, &buffersize, filename); if(!error) error = LodePNG_decode32(out, w, h, buffer, buffersize); free(buffer); return error; } #endif /*LODEPNG_COMPILE_DISK*/ void LodePNG_DecodeSettings_init(LodePNG_DecodeSettings* settings) { settings->color_convert = 1; #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS settings->readTextChunks = 1; #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ settings->ignoreCrc = 0; #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS settings->rememberUnknownChunks = 0; #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ LodeZlib_DecompressSettings_init(&settings->zlibsettings); } void LodePNG_Decoder_init(LodePNG_Decoder* decoder) { LodePNG_DecodeSettings_init(&decoder->settings); LodePNG_InfoRaw_init(&decoder->infoRaw); LodePNG_InfoPng_init(&decoder->infoPng); decoder->error = 1; } void LodePNG_Decoder_cleanup(LodePNG_Decoder* decoder) { LodePNG_InfoRaw_cleanup(&decoder->infoRaw); LodePNG_InfoPng_cleanup(&decoder->infoPng); } void LodePNG_Decoder_copy(LodePNG_Decoder* dest, const LodePNG_Decoder* source) { LodePNG_Decoder_cleanup(dest); *dest = *source; LodePNG_InfoRaw_init(&dest->infoRaw); LodePNG_InfoPng_init(&dest->infoPng); dest->error = LodePNG_InfoRaw_copy(&dest->infoRaw, &source->infoRaw); if(dest->error) return; dest->error = LodePNG_InfoPng_copy(&dest->infoPng, &source->infoPng); if(dest->error) return; } #endif /*LODEPNG_COMPILE_DECODER*/ #ifdef LODEPNG_COMPILE_ENCODER /* ////////////////////////////////////////////////////////////////////////// */ /* / PNG Encoder / */ /* ////////////////////////////////////////////////////////////////////////// */ /*chunkName must be string of 4 characters*/ static unsigned addChunk(ucvector* out, const char* chunkName, const unsigned char* data, size_t length) { unsigned error = LodePNG_create_chunk(&out->data, &out->size, (unsigned)length, chunkName, data); if(error) return error; out->allocsize = out->size; /*fix the allocsize again*/ return 0; } static void writeSignature(ucvector* out) { /*8 bytes PNG signature*/ ucvector_push_back(out, 137); ucvector_push_back(out, 80); ucvector_push_back(out, 78); ucvector_push_back(out, 71); ucvector_push_back(out, 13); ucvector_push_back(out, 10); ucvector_push_back(out, 26); ucvector_push_back(out, 10); } static unsigned addChunk_IHDR(ucvector* out, unsigned w, unsigned h, unsigned bitDepth, unsigned colorType, unsigned interlaceMethod) { unsigned error = 0; ucvector header; ucvector_init(&header); LodePNG_add32bitInt(&header, w); /*width*/ LodePNG_add32bitInt(&header, h); /*height*/ ucvector_push_back(&header, (unsigned char)bitDepth); /*bit depth*/ ucvector_push_back(&header, (unsigned char)colorType); /*color type*/ ucvector_push_back(&header, 0); /*compression method*/ ucvector_push_back(&header, 0); /*filter method*/ ucvector_push_back(&header, interlaceMethod); /*interlace method*/ error = addChunk(out, "IHDR", header.data, header.size); ucvector_cleanup(&header); return error; } static unsigned addChunk_PLTE(ucvector* out, const LodePNG_InfoColor* info) { unsigned error = 0; size_t i; ucvector PLTE; ucvector_init(&PLTE); for(i = 0; i < info->palettesize * 4; i++) if(i % 4 != 3) ucvector_push_back(&PLTE, info->palette[i]); /*add all channels except alpha channel*/ error = addChunk(out, "PLTE", PLTE.data, PLTE.size); ucvector_cleanup(&PLTE); return error; } static unsigned addChunk_tRNS(ucvector* out, const LodePNG_InfoColor* info) { unsigned error = 0; size_t i; ucvector tRNS; ucvector_init(&tRNS); if(info->colorType == 3) { for(i = 0; i < info->palettesize; i++) ucvector_push_back(&tRNS, info->palette[4 * i + 3]); /*add only alpha channel*/ } else if(info->colorType == 0) { if(info->key_defined) { ucvector_push_back(&tRNS, (unsigned char)(info->key_r / 256)); ucvector_push_back(&tRNS, (unsigned char)(info->key_r % 256)); } } else if(info->colorType == 2) { if(info->key_defined) { ucvector_push_back(&tRNS, (unsigned char)(info->key_r / 256)); ucvector_push_back(&tRNS, (unsigned char)(info->key_r % 256)); ucvector_push_back(&tRNS, (unsigned char)(info->key_g / 256)); ucvector_push_back(&tRNS, (unsigned char)(info->key_g % 256)); ucvector_push_back(&tRNS, (unsigned char)(info->key_b / 256)); ucvector_push_back(&tRNS, (unsigned char)(info->key_b % 256)); } } error = addChunk(out, "tRNS", tRNS.data, tRNS.size); ucvector_cleanup(&tRNS); return error; } static unsigned addChunk_IDAT(ucvector* out, const unsigned char* data, size_t datasize, LodeZlib_DeflateSettings* zlibsettings) { ucvector zlibdata; unsigned error = 0; /*compress with the Zlib compressor*/ ucvector_init(&zlibdata); error = LodePNG_compress(&zlibdata.data, &zlibdata.size, data, datasize, zlibsettings); if(!error) error = addChunk(out, "IDAT", zlibdata.data, zlibdata.size); ucvector_cleanup(&zlibdata); return error; } static unsigned addChunk_IEND(ucvector* out) { unsigned error = 0; error = addChunk(out, "IEND", 0, 0); return error; } #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS static unsigned addChunk_tEXt(ucvector* out, const char* keyword, const char* textstring) /*add text chunk*/ { unsigned error = 0; size_t i; ucvector text; ucvector_init(&text); for(i = 0; keyword[i] != 0; i++) ucvector_push_back(&text, (unsigned char)keyword[i]); ucvector_push_back(&text, 0); for(i = 0; textstring[i] != 0; i++) ucvector_push_back(&text, (unsigned char)textstring[i]); error = addChunk(out, "tEXt", text.data, text.size); ucvector_cleanup(&text); return error; } static unsigned addChunk_zTXt(ucvector* out, const char* keyword, const char* textstring, LodeZlib_DeflateSettings* zlibsettings) { unsigned error = 0; ucvector data, compressed; size_t i, textsize = strlen(textstring); ucvector_init(&data); ucvector_init(&compressed); for(i = 0; keyword[i] != 0; i++) ucvector_push_back(&data, (unsigned char)keyword[i]); ucvector_push_back(&data, 0); /* 0 termination char*/ ucvector_push_back(&data, 0); /*compression method: 0*/ error = LodePNG_compress(&compressed.data, &compressed.size, (unsigned char*)textstring, textsize, zlibsettings); if(!error) { for(i = 0; i < compressed.size; i++) ucvector_push_back(&data, compressed.data[i]); error = addChunk(out, "zTXt", data.data, data.size); } ucvector_cleanup(&compressed); ucvector_cleanup(&data); return error; } static unsigned addChunk_iTXt(ucvector* out, unsigned compressed, const char* keyword, const char* langtag, const char* transkey, const char* textstring, LodeZlib_DeflateSettings* zlibsettings) { unsigned error = 0; ucvector data, compressed_data; size_t i, textsize = strlen(textstring); ucvector_init(&data); for(i = 0; keyword[i] != 0; i++) ucvector_push_back(&data, (unsigned char)keyword[i]); ucvector_push_back(&data, 0); /*null termination char*/ ucvector_push_back(&data, compressed ? 1 : 0); /*compression flag*/ ucvector_push_back(&data, 0); /*compression method*/ for(i = 0; langtag[i] != 0; i++) ucvector_push_back(&data, (unsigned char)langtag[i]); ucvector_push_back(&data, 0); /*null termination char*/ for(i = 0; transkey[i] != 0; i++) ucvector_push_back(&data, (unsigned char)transkey[i]); ucvector_push_back(&data, 0); /*null termination char*/ if(compressed) { ucvector_init(&compressed_data); error = LodePNG_compress(&compressed_data.data, &compressed_data.size, (unsigned char*)textstring, textsize, zlibsettings); if(!error) { for(i = 0; i < compressed_data.size; i++) ucvector_push_back(&data, compressed_data.data[i]); for(i = 0; textstring[i] != 0; i++) ucvector_push_back(&data, (unsigned char)textstring[i]); } } else /*not compressed*/ { for(i = 0; textstring[i] != 0; i++) ucvector_push_back(&data, (unsigned char)textstring[i]); } if(!error) error = addChunk(out, "iTXt", data.data, data.size); ucvector_cleanup(&data); return error; } static unsigned addChunk_bKGD(ucvector* out, const LodePNG_InfoPng* info) { unsigned error = 0; ucvector bKGD; ucvector_init(&bKGD); if(info->color.colorType == 0 || info->color.colorType == 4) { ucvector_push_back(&bKGD, (unsigned char)(info->background_r / 256)); ucvector_push_back(&bKGD, (unsigned char)(info->background_r % 256)); } else if(info->color.colorType == 2 || info->color.colorType == 6) { ucvector_push_back(&bKGD, (unsigned char)(info->background_r / 256)); ucvector_push_back(&bKGD, (unsigned char)(info->background_r % 256)); ucvector_push_back(&bKGD, (unsigned char)(info->background_g / 256)); ucvector_push_back(&bKGD, (unsigned char)(info->background_g % 256)); ucvector_push_back(&bKGD, (unsigned char)(info->background_b / 256)); ucvector_push_back(&bKGD, (unsigned char)(info->background_b % 256)); } else if(info->color.colorType == 3) { ucvector_push_back(&bKGD, (unsigned char)(info->background_r % 256)); /*palette index*/ } error = addChunk(out, "bKGD", bKGD.data, bKGD.size); ucvector_cleanup(&bKGD); return error; } static unsigned addChunk_tIME(ucvector* out, const LodePNG_Time* time) { unsigned error = 0; unsigned char* data = (unsigned char*)malloc(7); if(!data) return 9948; data[0] = (unsigned char)(time->year / 256); data[1] = (unsigned char)(time->year % 256); data[2] = time->month; data[3] = time->day; data[4] = time->hour; data[5] = time->minute; data[6] = time->second; error = addChunk(out, "tIME", data, 7); free(data); return error; } static unsigned addChunk_pHYs(ucvector* out, const LodePNG_InfoPng* info) { unsigned error = 0; ucvector data; ucvector_init(&data); LodePNG_add32bitInt(&data, info->phys_x); LodePNG_add32bitInt(&data, info->phys_y); ucvector_push_back(&data, info->phys_unit); error = addChunk(out, "pHYs", data.data, data.size); ucvector_cleanup(&data); return error; } #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ static void filterScanline(unsigned char* out, const unsigned char* scanline, const unsigned char* prevline, size_t length, size_t bytewidth, unsigned char filterType) { size_t i; switch(filterType) { case 0: if(prevline) for(i = 0; i < length; i++) out[i] = scanline[i]; else for(i = 0; i < length; i++) out[i] = scanline[i]; break; case 1: if(prevline) { for(i = 0; i < bytewidth; i++) out[i] = scanline[i]; for(i = bytewidth; i < length ; i++) out[i] = scanline[i] - scanline[i - bytewidth]; } else { for(i = 0; i < bytewidth; i++) out[i] = scanline[i]; for(i = bytewidth; i < length; i++) out[i] = scanline[i] - scanline[i - bytewidth]; } break; case 2: if(prevline) for(i = 0; i < length; i++) out[i] = scanline[i] - prevline[i]; else for(i = 0; i < length; i++) out[i] = scanline[i]; break; case 3: if(prevline) { for(i = 0; i < bytewidth; i++) out[i] = scanline[i] - prevline[i] / 2; for(i = bytewidth; i < length; i++) out[i] = scanline[i] - ((scanline[i - bytewidth] + prevline[i]) / 2); } else { for(i = 0; i < length; i++) out[i] = scanline[i]; for(i = bytewidth; i < length; i++) out[i] = scanline[i] - scanline[i - bytewidth] / 2; } break; case 4: if(prevline) { for(i = 0; i < bytewidth; i++) out[i] = (unsigned char)(scanline[i] - paethPredictor(0, prevline[i], 0)); for(i = bytewidth; i < length; i++) out[i] = (unsigned char)(scanline[i] - paethPredictor(scanline[i - bytewidth], prevline[i], prevline[i - bytewidth])); } else { for(i = 0; i < bytewidth; i++) out[i] = scanline[i]; for(i = bytewidth; i < length; i++) out[i] = (unsigned char)(scanline[i] - paethPredictor(scanline[i - bytewidth], 0, 0)); } break; default: return; /*unexisting filter type given*/ } } static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, const LodePNG_InfoColor* info) { /* For PNG filter method 0 out must be a buffer with as size: h + (w * h * bpp + 7) / 8, because there are the scanlines with 1 extra byte per scanline There is a nice heuristic described here: http://www.cs.toronto.edu/~cosmin/pngtech/optipng.html. It says: * If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e. use fixed filtering, with the filter None). * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply all five filters and select the filter that produces the smallest sum of absolute values per row. Here the above method is used mostly. Note though that it appears to be better to use the adaptive filtering on the plasma 8-bit palette example, but that image isn't the best reference for palette images in general. */ unsigned bpp = LodePNG_InfoColor_getBpp(info); size_t linebytes = (w * bpp + 7) / 8; /*the width of a scanline in bytes, not including the filter type*/ size_t bytewidth = (bpp + 7) / 8; /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ const unsigned char* prevline = 0; unsigned x, y; unsigned heuristic; unsigned error = 0; if(bpp == 0) return 31; /*invalid color type*/ /*choose heuristic as described above*/ if(info->colorType == 3 || info->bitDepth < 8) heuristic = 0; else heuristic = 1; if(heuristic == 0) /*None filtertype for everything*/ { for(y = 0; y < h; y++) { size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ size_t inindex = linebytes * y; const unsigned TYPE = 0; out[outindex] = TYPE; /*filter type byte*/ filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, TYPE); prevline = &in[inindex]; } } else if(heuristic == 1) /*adaptive filtering*/ { size_t sum[5]; ucvector attempt[5]; /*five filtering attempts, one for each filter type*/ size_t smallest = 0; unsigned type, bestType = 0; for(type = 0; type < 5; type++) ucvector_init(&attempt[type]); for(type = 0; type < 5; type++) { if(!ucvector_resize(&attempt[type], linebytes)) { error = 9949; break; } } if(!error) { for(y = 0; y < h; y++) { /*try the 5 filter types*/ for(type = 0; type < 5; type++) { filterScanline(attempt[type].data, &in[y * linebytes], prevline, linebytes, bytewidth, type); /*calculate the sum of the result*/ sum[type] = 0; for(x = 0; x < attempt[type].size; x+=3) sum[type] += attempt[type].data[x]; /*note that not all pixels are checked to speed this up while still having probably the best choice*/ /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/ if(type == 0 || sum[type] < smallest) { bestType = type; smallest = sum[type]; } } prevline = &in[y * linebytes]; /*now fill the out values*/ out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ for(x = 0; x < linebytes; x++) out[y * (linebytes + 1) + 1 + x] = attempt[bestType].data[x]; } } for(type = 0; type < 5; type++) ucvector_cleanup(&attempt[type]); } #if 0 /*deflate the scanline with a fixed tree after every filter attempt to see which one deflates best. This is slow, and _does not work as expected_: the heuristic gives smaller result!*/ else if(heuristic == 2) /*adaptive filtering by using deflate*/ { size_t size[5]; ucvector attempt[5]; /*five filtering attempts, one for each filter type*/ size_t smallest; unsigned type = 0, bestType = 0; unsigned char* dummy; LodeZlib_DeflateSettings deflatesettings = LodeZlib_defaultDeflateSettings; deflatesettings.btype = 1; /*use fixed tree on the attempts so that the tree is not adapted to the filtertype on purpose, to simulate the true case where the tree is the same for the whole image*/ for(type = 0; type < 5; type++) { ucvector_init(&attempt[type]); ucvector_resize(&attempt[type], linebytes); } for(y = 0; y < h; y++) /*try the 5 filter types*/ { for(type = 0; type < 5; type++) { filterScanline(attempt[type].data, &in[y * linebytes], prevline, linebytes, bytewidth, type); size[type] = 0; dummy = 0; LodePNG_compress(&dummy, &size[type], attempt[type].data, attempt[type].size, &deflatesettings); free(dummy); /*check if this is smallest size (or if type == 0 it's the first case so always store the values)*/ if(type == 0 || size[type] < smallest) { bestType = type; smallest = size[type]; } } prevline = &in[y * linebytes]; out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ for(x = 0; x < linebytes; x++) out[y * (linebytes + 1) + 1 + x] = attempt[bestType].data[x]; } for(type = 0; type < 5; type++) ucvector_cleanup(&attempt[type]); } #endif return error; } static void addPaddingBits(unsigned char* out, const unsigned char* in, size_t olinebits, size_t ilinebits, unsigned h) { /*The opposite of the removePaddingBits function olinebits must be >= ilinebits*/ unsigned y; size_t diff = olinebits - ilinebits; size_t obp = 0, ibp = 0; /*bit pointers*/ for(y = 0; y < h; y++) { size_t x; for(x = 0; x < ilinebits; x++) { unsigned char bit = readBitFromReversedStream(&ibp, in); setBitOfReversedStream(&obp, out, bit); } /*obp += diff; --> no, fill in some value in the padding bits too, to avoid "Use of uninitialised value of size ###" warning from valgrind*/ for(x = 0; x < diff; x++) setBitOfReversedStream(&obp, out, 0); } } static void Adam7_interlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) { /*Note: this function works on image buffers WITHOUT padding bits at end of scanlines with non-multiple-of-8 bit amounts, only between reduced images is padding*/ unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8]; unsigned i; Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); if(bpp >= 8) { for(i = 0; i < 7; i++) { unsigned x, y, b; size_t bytewidth = bpp / 8; for(y = 0; y < passh[i]; y++) for(x = 0; x < passw[i]; x++) { size_t pixelinstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth; size_t pixeloutstart = passstart[i] + (y * passw[i] + x) * bytewidth; for(b = 0; b < bytewidth; b++) { out[pixeloutstart + b] = in[pixelinstart + b]; } } } } else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ { for(i = 0; i < 7; i++) { unsigned x, y, b; unsigned ilinebits = bpp * passw[i]; unsigned olinebits = bpp * w; size_t obp, ibp; /*bit pointers (for out and in buffer)*/ for(y = 0; y < passh[i]; y++) for(x = 0; x < passw[i]; x++) { ibp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp; obp = (8 * passstart[i]) + (y * ilinebits + x * bpp); for(b = 0; b < bpp; b++) { unsigned char bit = readBitFromReversedStream(&ibp, in); setBitOfReversedStream(&obp, out, bit); } } } } } /*out must be buffer big enough to contain uncompressed IDAT chunk data, and in must contain the full image*/ static unsigned preProcessScanlines(unsigned char** out, size_t* outsize, const unsigned char* in, const LodePNG_InfoPng* infoPng) /*return value is error*/ { /* This function converts the pure 2D image with the PNG's colortype, into filtered-padded-interlaced data. Steps: *) if no Adam7: 1) add padding bits (= posible extra bits per scanline if bpp < 8) 2) filter *) if adam7: 1) Adam7_interlace 2) 7x add padding bits 3) 7x filter */ unsigned bpp = LodePNG_InfoColor_getBpp(&infoPng->color); unsigned w = infoPng->width; unsigned h = infoPng->height; unsigned error = 0; if(infoPng->interlaceMethod == 0) { *outsize = h + (h * ((w * bpp + 7) / 8)); /*image size plus an extra byte per scanline + possible padding bits*/ *out = (unsigned char*)malloc(*outsize); if(!(*out) && (*outsize)) error = 9950; if(!error) { if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8) /*non multiple of 8 bits per scanline, padding bits needed per scanline*/ { ucvector padded; ucvector_init(&padded); if(!ucvector_resize(&padded, h * ((w * bpp + 7) / 8))) error = 9951; if(!error) { addPaddingBits(padded.data, in, ((w * bpp + 7) / 8) * 8, w * bpp, h); error = filter(*out, padded.data, w, h, &infoPng->color); } ucvector_cleanup(&padded); } else error = filter(*out, in, w, h, &infoPng->color); /*we can immediatly filter into the out buffer, no other steps needed*/ } } else /*interlaceMethod is 1 (Adam7)*/ { unsigned char* adam7 = (unsigned char*)malloc((h * w * bpp + 7) / 8); if(!adam7 && ((h * w * bpp + 7) / 8)) error = 9952; /*malloc failed*/ while(!error) /*not a real while loop, used to break out to cleanup to avoid a goto*/ { unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8]; unsigned i; Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); *outsize = filter_passstart[7]; /*image size plus an extra byte per scanline + possible padding bits*/ *out = (unsigned char*)malloc(*outsize); if(!(*out) && (*outsize)) { error = 9953; break; } Adam7_interlace(adam7, in, w, h, bpp); for(i = 0; i < 7; i++) { if(bpp < 8) { ucvector padded; ucvector_init(&padded); if(!ucvector_resize(&padded, h * ((w * bpp + 7) / 8))) error = 9954; if(!error) { addPaddingBits(&padded.data[padded_passstart[i]], &adam7[passstart[i]], ((passw[i] * bpp + 7) / 8) * 8, passw[i] * bpp, passh[i]); error = filter(&(*out)[filter_passstart[i]], &padded.data[padded_passstart[i]], passw[i], passh[i], &infoPng->color); } ucvector_cleanup(&padded); } else { error = filter(&(*out)[filter_passstart[i]], &adam7[padded_passstart[i]], passw[i], passh[i], &infoPng->color); } } break; } free(adam7); } return error; } /*palette must have 4 * palettesize bytes allocated*/ static unsigned isPaletteFullyOpaque(const unsigned char* palette, size_t palettesize) /*palette given in format RGBARGBARGBARGBA...*/ { size_t i; for(i = 0; i < palettesize; i++) { if(palette[4 * i + 3] != 255) return 0; } return 1; } /*this function checks if the input image given by the user has no transparent pixels*/ static unsigned isFullyOpaque(const unsigned char* image, unsigned w, unsigned h, const LodePNG_InfoColor* info) { /*TODO: When the user specified a color key for the input image, then this function must also check for pixels that are the same as the color key and treat those as transparent.*/ unsigned i, numpixels = w * h; if(info->colorType == 6) { if(info->bitDepth == 8) { for(i = 0; i < numpixels; i++) if(image[i * 4 + 3] != 255) return 0; } else { for(i = 0; i < numpixels; i++) if(image[i * 8 + 6] != 255 || image[i * 8 + 7] != 255) return 0; } return 1; /*no single pixel with alpha channel other than 255 found*/ } else if(info->colorType == 4) { if(info->bitDepth == 8) { for(i = 0; i < numpixels; i++) if(image[i * 2 + 1] != 255) return 0; } else { for(i = 0; i < numpixels; i++) if(image[i * 4 + 2] != 255 || image[i * 4 + 3] != 255) return 0; } return 1; /*no single pixel with alpha channel other than 255 found*/ } else if(info->colorType == 3) { /*when there's a palette, we could check every pixel for translucency, but much quicker is to just check the palette*/ return(isPaletteFullyOpaque(info->palette, info->palettesize)); } return 0; /*color type that isn't supported by this function yet, so assume there is transparency to be safe*/ } #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS static unsigned addUnknownChunks(ucvector* out, unsigned char* data, size_t datasize) { unsigned char* inchunk = data; while((size_t)(inchunk - data) < datasize) { unsigned error = LodePNG_append_chunk(&out->data, &out->size, inchunk); if(error) return error; /*error: not enough memory*/ out->allocsize = out->size; /*fix the allocsize again*/ inchunk = LodePNG_chunk_next(inchunk); } return 0; } #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ void LodePNG_encode(LodePNG_Encoder* encoder, unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) { LodePNG_InfoPng info; ucvector outv; unsigned char* data = 0; /*uncompressed version of the IDAT chunk data*/ size_t datasize = 0; /*provide some proper output values if error will happen*/ *out = 0; *outsize = 0; encoder->error = 0; info = encoder->infoPng; /*UNSAFE copy to avoid having to cleanup! but we will only change primitive parameters, and not invoke the cleanup function nor touch the palette's buffer so we use it safely*/ info.width = w; info.height = h; if(encoder->settings.autoLeaveOutAlphaChannel && isFullyOpaque(image, w, h, &encoder->infoRaw.color)) { /*go to a color type without alpha channel*/ if(info.color.colorType == 6) info.color.colorType = 2; else if(info.color.colorType == 4) info.color.colorType = 0; } if(encoder->settings.zlibsettings.windowSize > 32768) { encoder->error = 60; return; } /*error: windowsize larger than allowed*/ if(encoder->settings.zlibsettings.btype > 2) { encoder->error = 61; return; } /*error: unexisting btype*/ if(encoder->infoPng.interlaceMethod > 1) { encoder->error = 71; return; } /*error: unexisting interlace mode*/ if((encoder->error = checkColorValidity(info.color.colorType, info.color.bitDepth))) return; /*error: unexisting color type given*/ if((encoder->error = checkColorValidity(encoder->infoRaw.color.colorType, encoder->infoRaw.color.bitDepth))) return; /*error: unexisting color type given*/ if(!LodePNG_InfoColor_equal(&encoder->infoRaw.color, &info.color)) { unsigned char* converted; size_t size = (w * h * LodePNG_InfoColor_getBpp(&info.color) + 7) / 8; if((info.color.colorType != 6 && info.color.colorType != 2) || (info.color.bitDepth != 8)) { encoder->error = 59; return; } /*for the output image, only these types are supported*/ converted = (unsigned char*)malloc(size); if(!converted && size) encoder->error = 9955; /*error: malloc failed*/ if(!encoder->error) encoder->error = LodePNG_convert(converted, image, &info.color, &encoder->infoRaw.color, w, h); if(!encoder->error) preProcessScanlines(&data, &datasize, converted, &info);/*filter(data.data, converted.data, w, h, LodePNG_InfoColor_getBpp(&info.color));*/ free(converted); } else preProcessScanlines(&data, &datasize, image, &info);/*filter(data.data, image, w, h, LodePNG_InfoColor_getBpp(&info.color));*/ ucvector_init(&outv); while(!encoder->error) /*not really a while loop, this is only used to break out if an error happens to avoid goto's to do the ucvector cleanup*/ { #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS size_t i; #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ /*write signature and chunks*/ writeSignature(&outv); /*IHDR*/ addChunk_IHDR(&outv, w, h, info.color.bitDepth, info.color.colorType, info.interlaceMethod); #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS /*unknown chunks between IHDR and PLTE*/ if(info.unknown_chunks.data[0]) { encoder->error = addUnknownChunks(&outv, info.unknown_chunks.data[0], info.unknown_chunks.datasize[0]); if(encoder->error) break; } #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ /*PLTE*/ if(info.color.colorType == 3) { if(info.color.palettesize == 0 || info.color.palettesize > 256) { encoder->error = 68; break; } addChunk_PLTE(&outv, &info.color); } if(encoder->settings.force_palette && (info.color.colorType == 2 || info.color.colorType == 6)) { if(info.color.palettesize == 0 || info.color.palettesize > 256) { encoder->error = 68; break; } addChunk_PLTE(&outv, &info.color); } /*tRNS*/ if(info.color.colorType == 3 && !isPaletteFullyOpaque(info.color.palette, info.color.palettesize)) addChunk_tRNS(&outv, &info.color); if((info.color.colorType == 0 || info.color.colorType == 2) && info.color.key_defined) addChunk_tRNS(&outv, &info.color); #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS /*bKGD (must come between PLTE and the IDAt chunks*/ if(info.background_defined) addChunk_bKGD(&outv, &info); /*pHYs (must come before the IDAT chunks)*/ if(info.phys_defined) addChunk_pHYs(&outv, &info); #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS /*unknown chunks between PLTE and IDAT*/ if(info.unknown_chunks.data[1]) { encoder->error = addUnknownChunks(&outv, info.unknown_chunks.data[1], info.unknown_chunks.datasize[1]); if(encoder->error) break; } #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ /*IDAT (multiple IDAT chunks must be consecutive)*/ encoder->error = addChunk_IDAT(&outv, data, datasize, &encoder->settings.zlibsettings); if(encoder->error) break; #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS /*tIME*/ if(info.time_defined) addChunk_tIME(&outv, &info.time); /*tEXt and/or zTXt*/ for(i = 0; i < info.text.num; i++) { if(strlen(info.text.keys[i]) > 79) { encoder->error = 66; break; } if(strlen(info.text.keys[i]) < 1) { encoder->error = 67; break; } if(encoder->settings.text_compression) addChunk_zTXt(&outv, info.text.keys[i], info.text.strings[i], &encoder->settings.zlibsettings); else addChunk_tEXt(&outv, info.text.keys[i], info.text.strings[i]); } /*LodePNG version id in text chunk*/ if(encoder->settings.add_id) { unsigned alread_added_id_text = 0; for(i = 0; i < info.text.num; i++) if(!strcmp(info.text.keys[i], "LodePNG")) { alread_added_id_text = 1; break; } if(alread_added_id_text == 0) addChunk_tEXt(&outv, "LodePNG", VERSION_STRING); /*it's shorter as tEXt than as zTXt chunk*/ } /*iTXt*/ for(i = 0; i < info.itext.num; i++) { if(strlen(info.itext.keys[i]) > 79) { encoder->error = 66; break; } if(strlen(info.itext.keys[i]) < 1) { encoder->error = 67; break; } addChunk_iTXt(&outv, encoder->settings.text_compression, info.itext.keys[i], info.itext.langtags[i], info.itext.transkeys[i], info.itext.strings[i], &encoder->settings.zlibsettings); } #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS /*unknown chunks between IDAT and IEND*/ if(info.unknown_chunks.data[2]) { encoder->error = addUnknownChunks(&outv, info.unknown_chunks.data[2], info.unknown_chunks.datasize[2]); if(encoder->error) break; } #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ /*IEND*/ addChunk_IEND(&outv); break; /*this isn't really a while loop; no error happened so break out now!*/ } free(data); /*instead of cleaning the vector up, give it to the output*/ *out = outv.data; *outsize = outv.size; } unsigned LodePNG_encode32(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) { unsigned error; LodePNG_Encoder encoder; LodePNG_Encoder_init(&encoder); LodePNG_encode(&encoder, out, outsize, image, w, h); error = encoder.error; LodePNG_Encoder_cleanup(&encoder); return error; } #ifdef LODEPNG_COMPILE_DISK unsigned LodePNG_encode32f(const char* filename, const unsigned char* image, unsigned w, unsigned h) { unsigned char* buffer; size_t buffersize; unsigned error = LodePNG_encode32(&buffer, &buffersize, image, w, h); LodePNG_saveFile(buffer, buffersize, filename); free(buffer); return error; } #endif /*LODEPNG_COMPILE_DISK*/ void LodePNG_EncodeSettings_init(LodePNG_EncodeSettings* settings) { LodeZlib_DeflateSettings_init(&settings->zlibsettings); settings->autoLeaveOutAlphaChannel = 1; settings->force_palette = 0; #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS settings->add_id = 1; settings->text_compression = 0; #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ } void LodePNG_Encoder_init(LodePNG_Encoder* encoder) { LodePNG_EncodeSettings_init(&encoder->settings); LodePNG_InfoPng_init(&encoder->infoPng); LodePNG_InfoRaw_init(&encoder->infoRaw); encoder->error = 1; } void LodePNG_Encoder_cleanup(LodePNG_Encoder* encoder) { LodePNG_InfoPng_cleanup(&encoder->infoPng); LodePNG_InfoRaw_cleanup(&encoder->infoRaw); } void LodePNG_Encoder_copy(LodePNG_Encoder* dest, const LodePNG_Encoder* source) { LodePNG_Encoder_cleanup(dest); *dest = *source; LodePNG_InfoPng_init(&dest->infoPng); LodePNG_InfoRaw_init(&dest->infoRaw); dest->error = LodePNG_InfoPng_copy(&dest->infoPng, &source->infoPng); if(dest->error) return; dest->error = LodePNG_InfoRaw_copy(&dest->infoRaw, &source->infoRaw); if(dest->error) return; } #endif /*LODEPNG_COMPILE_ENCODER*/ #endif /*LODEPNG_COMPILE_PNG*/ /* ////////////////////////////////////////////////////////////////////////// */ /* / File IO / */ /* ////////////////////////////////////////////////////////////////////////// */ #ifdef LODEPNG_COMPILE_DISK unsigned LodePNG_loadFile(unsigned char** out, size_t* outsize, const char* filename) /*designed for loading files from hard disk in a dynamically allocated buffer*/ { FILE* file; long size; /*provide some proper output values if error will happen*/ *out = 0; *outsize = 0; file = fopen(filename, "rb"); if(!file) return 78; /*get filesize:*/ fseek(file , 0 , SEEK_END); size = ftell(file); rewind(file); /*read contents of the file into the vector*/ *outsize = 0; *out = (unsigned char*)malloc((size_t)size); if(size && (*out)) (*outsize) = fread(*out, 1, (size_t)size, file); fclose(file); if(!(*out) && size) return 80; /*the above malloc failed*/ return 0; } /*write given buffer to the file, overwriting the file, it doesn't append to it.*/ unsigned LodePNG_saveFile(const unsigned char* buffer, size_t buffersize, const char* filename) { FILE* file; file = fopen(filename, "wb" ); if(!file) return 79; fwrite((char*)buffer , 1 , buffersize, file); fclose(file); return 0; } #endif /*LODEPNG_COMPILE_DISK*/ #ifdef __cplusplus /* ////////////////////////////////////////////////////////////////////////// */ /* / C++ RAII wrapper / */ /* ////////////////////////////////////////////////////////////////////////// */ namespace LodeZlib { unsigned decompress(std::vector& out, const std::vector& in, const LodeZlib_DecompressSettings& settings) { unsigned char* buffer = 0; size_t buffersize = 0; unsigned error = LodeZlib_decompress(&buffer, &buffersize, in.empty() ? 0 : &in[0], in.size(), &settings); if(buffer) { out.insert(out.end(), &buffer[0], &buffer[buffersize]); free(buffer); } return error; } unsigned compress(std::vector& out, const std::vector& in, const LodeZlib_DeflateSettings& settings) { unsigned char* buffer = 0; size_t buffersize = 0; unsigned error = LodeZlib_compress(&buffer, &buffersize, in.empty() ? 0 : &in[0], in.size(), &settings); if(buffer) { out.insert(out.end(), &buffer[0], &buffer[buffersize]); free(buffer); } return error; } } namespace LodePNG { Decoder::Decoder() { LodePNG_Decoder_init(this); } Decoder::~Decoder() { LodePNG_Decoder_cleanup(this); } void Decoder::operator=(const LodePNG_Decoder& other) { LodePNG_Decoder_copy(this, &other); } bool Decoder::hasError() const { return error != 0; } unsigned Decoder::getError() const { return error; } unsigned Decoder::getWidth() const { return infoPng.width; } unsigned Decoder::getHeight() const { return infoPng.height; } unsigned Decoder::getBpp() { return LodePNG_InfoColor_getBpp(&infoPng.color); } unsigned Decoder::getChannels() { return LodePNG_InfoColor_getChannels(&infoPng.color); } unsigned Decoder::isGreyscaleType() { return LodePNG_InfoColor_isGreyscaleType(&infoPng.color); } unsigned Decoder::isAlphaType() { return LodePNG_InfoColor_isAlphaType(&infoPng.color); } void Decoder::decode(std::vector& out, const unsigned char* in, size_t insize) { unsigned char* buffer; size_t buffersize; LodePNG_decode(this, &buffer, &buffersize, in, insize); if(buffer) { out.insert(out.end(), &buffer[0], &buffer[buffersize]); free(buffer); } } void Decoder::decode(std::vector& out, const std::vector& in) { decode(out, in.empty() ? 0 : &in[0], in.size()); } void Decoder::inspect(const unsigned char* in, size_t size) { LodePNG_inspect(this, in, size); } void Decoder::inspect(const std::vector& in) { inspect(in.empty() ? 0 : &in[0], in.size()); } const LodePNG_DecodeSettings& Decoder::getSettings() const { return settings; } LodePNG_DecodeSettings& Decoder::getSettings() { return settings; } void Decoder::setSettings(const LodePNG_DecodeSettings& settings) { this->settings = settings; } const LodePNG_InfoPng& Decoder::getInfoPng() const { return infoPng; } LodePNG_InfoPng& Decoder::getInfoPng() { return infoPng; } void Decoder::setInfoPng(const LodePNG_InfoPng& info) { error = LodePNG_InfoPng_copy(&this->infoPng, &info); } void Decoder::swapInfoPng(LodePNG_InfoPng& info) { LodePNG_InfoPng_swap(&this->infoPng, &info); } const LodePNG_InfoRaw& Decoder::getInfoRaw() const { return infoRaw; } LodePNG_InfoRaw& Decoder::getInfoRaw() { return infoRaw; } void Decoder::setInfoRaw(const LodePNG_InfoRaw& info) { error = LodePNG_InfoRaw_copy(&this->infoRaw, &info); } /* ////////////////////////////////////////////////////////////////////////// */ Encoder::Encoder() { LodePNG_Encoder_init(this); } Encoder::~Encoder() { LodePNG_Encoder_cleanup(this); } void Encoder::operator=(const LodePNG_Encoder& other) { LodePNG_Encoder_copy(this, &other); } bool Encoder::hasError() const { return error != 0; } unsigned Encoder::getError() const { return error; } void Encoder::encode(std::vector& out, const unsigned char* image, unsigned w, unsigned h) { unsigned char* buffer; size_t buffersize; LodePNG_encode(this, &buffer, &buffersize, image, w, h); if(buffer) { out.insert(out.end(), &buffer[0], &buffer[buffersize]); free(buffer); } } void Encoder::encode(std::vector& out, const std::vector& image, unsigned w, unsigned h) { encode(out, image.empty() ? 0 : &image[0], w, h); } void Encoder::clearPalette() { LodePNG_InfoColor_clearPalette(&infoPng.color); } void Encoder::addPalette(unsigned char r, unsigned char g, unsigned char b, unsigned char a) { error = LodePNG_InfoColor_addPalette(&infoPng.color, r, g, b, a); } #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS void Encoder::clearText() { LodePNG_Text_clear(&infoPng.text); } void Encoder::addText(const std::string& key, const std::string& str) { error = LodePNG_Text_add(&infoPng.text, key.c_str(), str.c_str()); } void Encoder::clearIText() { LodePNG_IText_clear(&infoPng.itext); } void Encoder::addIText(const std::string& key, const std::string& langtag, const std::string& transkey, const std::string& str) { error = LodePNG_IText_add(&infoPng.itext, key.c_str(), langtag.c_str(), transkey.c_str(), str.c_str()); } #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ const LodePNG_EncodeSettings& Encoder::getSettings() const { return settings; } LodePNG_EncodeSettings& Encoder::getSettings() { return settings; } void Encoder::setSettings(const LodePNG_EncodeSettings& settings) { this->settings = settings; } const LodePNG_InfoPng& Encoder::getInfoPng() const { return infoPng; } LodePNG_InfoPng& Encoder::getInfoPng() { return infoPng; } void Encoder::setInfoPng(const LodePNG_InfoPng& info) { error = LodePNG_InfoPng_copy(&this->infoPng, &info); } void Encoder::swapInfoPng(LodePNG_InfoPng& info) { LodePNG_InfoPng_swap(&this->infoPng, &info); } const LodePNG_InfoRaw& Encoder::getInfoRaw() const { return infoRaw; } LodePNG_InfoRaw& Encoder::getInfoRaw() { return infoRaw; } void Encoder::setInfoRaw(const LodePNG_InfoRaw& info) { error = LodePNG_InfoRaw_copy(&this->infoRaw, &info); } /* ////////////////////////////////////////////////////////////////////////// */ #ifdef LODEPNG_COMPILE_DISK void loadFile(std::vector& buffer, const std::string& filename) //designed for loading files from hard disk in an std::vector { std::ifstream file(filename.c_str(), std::ios::in|std::ios::binary|std::ios::ate); /*get filesize*/ std::streamsize size = 0; if(file.seekg(0, std::ios::end).good()) size = file.tellg(); if(file.seekg(0, std::ios::beg).good()) size -= file.tellg(); /*read contents of the file into the vector*/ buffer.resize(size_t(size)); if(size > 0) file.read((char*)(&buffer[0]), size); } /*write given buffer to the file, overwriting the file, it doesn't append to it.*/ void saveFile(const std::vector& buffer, const std::string& filename) { std::ofstream file(filename.c_str(), std::ios::out|std::ios::binary); file.write(buffer.empty() ? 0 : (char*)&buffer[0], std::streamsize(buffer.size())); } #endif /*LODEPNG_COMPILE_DISK*/ /* ////////////////////////////////////////////////////////////////////////// */ unsigned decode(std::vector& out, unsigned& w, unsigned& h, const unsigned char* in, unsigned size, unsigned colorType, unsigned bitDepth) { Decoder decoder; decoder.getInfoRaw().color.colorType = colorType; decoder.getInfoRaw().color.bitDepth = bitDepth; decoder.decode(out, in, size); w = decoder.getWidth(); h = decoder.getHeight(); return decoder.getError(); } unsigned decode(std::vector& out, unsigned& w, unsigned& h, const std::vector& in, unsigned colorType, unsigned bitDepth) { return decode(out, w, h, in.empty() ? 0 : &in[0], (unsigned)in.size(), colorType, bitDepth); } #ifdef LODEPNG_COMPILE_DISK unsigned decode(std::vector& out, unsigned& w, unsigned& h, const std::string& filename, unsigned colorType, unsigned bitDepth) { std::vector buffer; loadFile(buffer, filename); return decode(out, w, h, buffer, colorType, bitDepth); } #endif /*LODEPNG_COMPILE_DISK*/ unsigned encode(std::vector& out, const unsigned char* in, unsigned w, unsigned h, unsigned colorType, unsigned bitDepth) { Encoder encoder; encoder.getInfoRaw().color.colorType = colorType; encoder.getInfoRaw().color.bitDepth = bitDepth; encoder.encode(out, in, w, h); return encoder.getError(); } unsigned encode(std::vector& out, const std::vector& in, unsigned w, unsigned h, unsigned colorType, unsigned bitDepth) { return encode(out, in.empty() ? 0 : &in[0], w, h, colorType, bitDepth); } #ifdef LODEPNG_COMPILE_DISK unsigned encode(const std::string& filename, const unsigned char* in, unsigned w, unsigned h, unsigned colorType, unsigned bitDepth) { std::vector buffer; Encoder encoder; encoder.getInfoRaw().color.colorType = colorType; encoder.getInfoRaw().color.bitDepth = bitDepth; encoder.encode(buffer, in, w, h); if(!encoder.hasError()) saveFile(buffer, filename); return encoder.getError(); } unsigned encode(const std::string& filename, const std::vector& in, unsigned w, unsigned h, unsigned colorType, unsigned bitDepth) { return encode(filename, in.empty() ? 0 : &in[0], w, h, colorType, bitDepth); } #endif /*LODEPNG_COMPILE_DISK*/ } #endif /*__cplusplus C++ RAII wrapper*/ passage-4+dfsg1.orig/minorGems/graphics/converters/JPEGImageConverter.h0000640000175000017500000000317407272307726024735 0ustar pabspabs/* * Modification History * * 2001-April-27 Jason Rohrer * Created. */ #ifndef JPEG_IMAGE_CONVERTER_INCLUDED #define JPEG_IMAGE_CONVERTER_INCLUDED #include "minorGems/graphics/ImageConverter.h" /** * JPEG implementation of the image conversion interface. * * Implementations are platform dependent. * * @author Jason Rohrer */ class JPEGImageConverter : public ImageConverter { public: /** * Constructs a JPEGImageConverter. * * @param inQuality a quality value in [0,100] for compression. * 100 specifies highest quality. */ JPEGImageConverter( int inQuality ); /** * Sets the compression quality. * * @param inQuality a quality value in [0,100]. 100 * specifies highest quality. */ void setQuality( int inQuality ); /** * Gets the compression quality. * * @return a quality value in [0,100]. 100 * indicates highest quality. */ int getQuality(); // implement the ImageConverter interface virtual void formatImage( Image *inImage, OutputStream *inStream ); virtual Image *deformatImage( InputStream *inStream ); private: int mQuality; }; inline JPEGImageConverter::JPEGImageConverter( int inQuality ) : mQuality( inQuality ) { if( mQuality > 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 passage-4+dfsg1.orig/minorGems/graphics/converters/jpegConverterTestCompile0000750000175000017500000000020307272310031026064 0ustar pabspabsg++ -I../../.. -ljpeg -o jpegConverterTest jpegConverterTest.cpp unix/JPEGImageConverterUnix.cpp ../../io/file/linux/PathLinux.cpp passage-4+dfsg1.orig/minorGems/graphics/converters/jpegConverterTest.cpp0000640000175000017500000000366307273016172025361 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; } passage-4+dfsg1.orig/minorGems/graphics/converters/lodepng.h0000640000175000017500000023637111341107257023001 0ustar pabspabs/* LodePNG version 20080927 Copyright (c) 2005-2008 Lode Vandevenne This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ #ifndef LODEPNG_H #define LODEPNG_H #include #include #include /* ////////////////////////////////////////////////////////////////////////// */ /* Code Sections */ /* ////////////////////////////////////////////////////////////////////////// */ /*The following defines can be commented disable code sections. Gives potential faster compile and smaller binary.*/ #define LODEPNG_COMPILE_ZLIB /*deflate&zlib encoder and deflate&zlib decoder*/ #define LODEPNG_COMPILE_PNG /*png encoder and png decoder*/ #define LODEPNG_COMPILE_DECODER /*deflate&zlib decoder and png decoder*/ #define LODEPNG_COMPILE_ENCODER /*deflate&zlib encoder and png encoder*/ #define LODEPNG_COMPILE_DISK /*the optional built in harddisk file loading and saving functions*/ #define LODEPNG_COMPILE_ANCILLARY_CHUNKS /*any code or struct datamember related to chunks other than IHDR, IDAT, PLTE, tRNS, IEND*/ #define LODEPNG_COMPILE_UNKNOWN_CHUNKS /*handling of unknown chunks*/ /* ////////////////////////////////////////////////////////////////////////// */ /* LodeFlate & LodeZlib Setting structs */ /* ////////////////////////////////////////////////////////////////////////// */ #ifdef LODEPNG_COMPILE_DECODER typedef struct LodeZlib_DecompressSettings { unsigned ignoreAdler32; } LodeZlib_DecompressSettings; extern const LodeZlib_DecompressSettings LodeZlib_defaultDecompressSettings; void LodeZlib_DecompressSettings_init(LodeZlib_DecompressSettings* settings); #endif /*LODEPNG_COMPILE_DECODER*/ #ifdef LODEPNG_COMPILE_ENCODER typedef struct LodeZlib_DeflateSettings /*deflate = compress*/ { /*LZ77 related settings*/ unsigned btype; /*the block type for LZ*/ unsigned useLZ77; /*whether or not to use LZ77*/ unsigned windowSize; /*the maximum is 32768*/ } LodeZlib_DeflateSettings; extern const LodeZlib_DeflateSettings LodeZlib_defaultDeflateSettings; void LodeZlib_DeflateSettings_init(LodeZlib_DeflateSettings* settings); #endif /*LODEPNG_COMPILE_ENCODER*/ #ifdef LODEPNG_COMPILE_ZLIB /* ////////////////////////////////////////////////////////////////////////// */ /* LodeFlate & LodeZlib */ /* ////////////////////////////////////////////////////////////////////////// */ #ifdef LODEPNG_COMPILE_DECODER /*This function reallocates the out buffer and appends the data. Either, *out must be NULL and *outsize must be 0, or, *out must be a valid buffer and *outsize its size in bytes.*/ unsigned LodeZlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in, size_t insize, const LodeZlib_DecompressSettings* settings); #endif /*LODEPNG_COMPILE_DECODER*/ #ifdef LODEPNG_COMPILE_ENCODER /*This function reallocates the out buffer and appends the data. Either, *out must be NULL and *outsize must be 0, or, *out must be a valid buffer and *outsize its size in bytes.*/ unsigned LodeZlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, size_t insize, const LodeZlib_DeflateSettings* settings); #endif /*LODEPNG_COMPILE_ENCODER*/ #endif /*LODEPNG_COMPILE_ZLIB*/ #ifdef LODEPNG_COMPILE_PNG /* ////////////////////////////////////////////////////////////////////////// */ /* LodePNG */ /* ////////////////////////////////////////////////////////////////////////// */ /*LodePNG_chunk functions: These functions need as input a large enough amount of allocated memory.*/ unsigned LodePNG_chunk_length(const unsigned char* chunk); /*get the length of the data of the chunk. Total chunk length has 12 bytes more.*/ void LodePNG_chunk_type(char type[5], const unsigned char* chunk); /*puts the 4-byte type in null terminated string*/ unsigned char LodePNG_chunk_type_equals(const unsigned char* chunk, const char* type); /*check if the type is the given type*/ /*properties of PNG chunks gotten from capitalization of chunk type name, as defined by the standard*/ unsigned char LodePNG_chunk_critical(const unsigned char* chunk); /*0: ancillary chunk, 1: it's one of the critical chunk types*/ unsigned char LodePNG_chunk_private(const unsigned char* chunk); /*0: public, 1: private*/ unsigned char LodePNG_chunk_safetocopy(const unsigned char* chunk); /*0: the chunk is unsafe to copy, 1: the chunk is safe to copy*/ unsigned char* LodePNG_chunk_data(unsigned char* chunk); /*get pointer to the data of the chunk*/ const unsigned char* LodePNG_chunk_data_const(const unsigned char* chunk); /*get pointer to the data of the chunk*/ unsigned LodePNG_chunk_check_crc(const unsigned char* chunk); /*returns 0 if the crc is correct, 1 if it's incorrect*/ void LodePNG_chunk_generate_crc(unsigned char* chunk); /*generates the correct CRC from the data and puts it in the last 4 bytes of the chunk*/ /*iterate to next chunks.*/ unsigned char* LodePNG_chunk_next(unsigned char* chunk); const unsigned char* LodePNG_chunk_next_const(const unsigned char* chunk); /*add chunks to out buffer. It reallocs the buffer to append the data. returns error code*/ unsigned LodePNG_append_chunk(unsigned char** out, size_t* outlength, const unsigned char* chunk); /*appends chunk that was already created, to the data. Returns pointer to start of appended chunk, or NULL if error happened*/ unsigned LodePNG_create_chunk(unsigned char** out, size_t* outlength, unsigned length, const char* type, const unsigned char* data); /*appends new chunk to out. Returns pointer to start of appended chunk, or NULL if error happened; may change memory address of out buffer*/ typedef struct LodePNG_InfoColor /*info about the color type of an image*/ { /*header (IHDR)*/ unsigned colorType; /*color type*/ unsigned bitDepth; /*bits per sample*/ /*palette (PLTE)*/ unsigned char* palette; /*palette in RGBARGBA... order*/ size_t palettesize; /*palette size in number of colors (amount of bytes is 4 * palettesize)*/ /*transparent color key (tRNS)*/ unsigned key_defined; /*is a transparent color key given?*/ unsigned key_r; /*red component of color key*/ unsigned key_g; /*green component of color key*/ unsigned key_b; /*blue component of color key*/ } LodePNG_InfoColor; void LodePNG_InfoColor_init(LodePNG_InfoColor* info); void LodePNG_InfoColor_cleanup(LodePNG_InfoColor* info); unsigned LodePNG_InfoColor_copy(LodePNG_InfoColor* dest, const LodePNG_InfoColor* source); /*Use these functions instead of allocating palette manually*/ void LodePNG_InfoColor_clearPalette(LodePNG_InfoColor* info); unsigned LodePNG_InfoColor_addPalette(LodePNG_InfoColor* info, unsigned char r, unsigned char g, unsigned char b, unsigned char a); /*add 1 color to the palette*/ /*additional color info*/ unsigned LodePNG_InfoColor_getBpp(const LodePNG_InfoColor* info); /*bits per pixel*/ unsigned LodePNG_InfoColor_getChannels(const LodePNG_InfoColor* info); /*amount of channels*/ unsigned LodePNG_InfoColor_isGreyscaleType(const LodePNG_InfoColor* info); /*is it a greyscale type? (colorType 0 or 4)*/ unsigned LodePNG_InfoColor_isAlphaType(const LodePNG_InfoColor* info); /*has it an alpha channel? (colorType 2 or 6)*/ #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS typedef struct LodePNG_Time /*LodePNG's encoder does not generate the current time. To make it add a time chunk the correct time has to be provided*/ { unsigned year; /*2 bytes*/ unsigned char month; /*1-12*/ unsigned char day; /*1-31*/ unsigned char hour; /*0-23*/ unsigned char minute; /*0-59*/ unsigned char second; /*0-60 (to allow for leap seconds)*/ } LodePNG_Time; typedef struct LodePNG_Text /*non-international text*/ { size_t num; char** keys; /*the keyword of a text chunk (e.g. "Comment")*/ char** strings; /*the actual text*/ } LodePNG_Text; void LodePNG_Text_init(LodePNG_Text* text); void LodePNG_Text_cleanup(LodePNG_Text* text); unsigned LodePNG_Text_copy(LodePNG_Text* dest, const LodePNG_Text* source); /*Use these functions instead of allocating the char**s manually*/ void LodePNG_Text_clear(LodePNG_Text* text); unsigned LodePNG_Text_add(LodePNG_Text* text, const char* key, const char* str); /*push back both texts at once*/ typedef struct LodePNG_IText /*international text*/ { size_t num; char** keys; /*the English keyword of the text chunk (e.g. "Comment")*/ char** langtags; /*the language tag for this text's international language, ISO/IEC 646 string, e.g. ISO 639 language tag*/ char** transkeys; /*keyword translated to the international language - UTF-8 string*/ char** strings; /*the actual international text - UTF-8 string*/ } LodePNG_IText; void LodePNG_IText_init(LodePNG_IText* text); void LodePNG_IText_cleanup(LodePNG_IText* text); unsigned LodePNG_IText_copy(LodePNG_IText* dest, const LodePNG_IText* source); /*Use these functions instead of allocating the char**s manually*/ void LodePNG_IText_clear(LodePNG_IText* text); unsigned LodePNG_IText_add(LodePNG_IText* text, const char* key, const char* langtag, const char* transkey, const char* str); /*push back the 4 texts of 1 chunk at once*/ #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS typedef struct LodePNG_UnknownChunks /*unknown chunks read from the PNG, or extra chunks the user wants to have added in the encoded PNG*/ { /*There are 3 buffers, one for each position in the PNG where unknown chunks can appear each buffer contains all unknown chunks for that position consecutively The 3 buffers are the unknown chunks between certain critical chunks: 0: IHDR-PLTE, 1: PLTE-IDAT, 2: IDAT-IEND*/ unsigned char* data[3]; size_t datasize[3]; /*size in bytes of the unknown chunks, given for protection*/ } LodePNG_UnknownChunks; void LodePNG_UnknownChunks_init(LodePNG_UnknownChunks* chunks); void LodePNG_UnknownChunks_cleanup(LodePNG_UnknownChunks* chunks); unsigned LodePNG_UnknownChunks_copy(LodePNG_UnknownChunks* dest, const LodePNG_UnknownChunks* src); #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ typedef struct LodePNG_InfoPng /*information about the PNG image, except pixels and sometimes except width and height*/ { /*header (IHDR), palette (PLTE) and transparency (tRNS)*/ unsigned width; /*width of the image in pixels (ignored by encoder, but filled in by decoder)*/ unsigned height; /*height of the image in pixels (ignored by encoder, but filled in by decoder)*/ unsigned compressionMethod; /*compression method of the original file*/ unsigned filterMethod; /*filter method of the original file*/ unsigned interlaceMethod; /*interlace method of the original file*/ LodePNG_InfoColor color; /*color type and bits, palette, transparency*/ #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS /*suggested background color (bKGD)*/ unsigned background_defined; /*is a suggested background color given?*/ unsigned background_r; /*red component of suggested background color*/ unsigned background_g; /*green component of suggested background color*/ unsigned background_b; /*blue component of suggested background color*/ /*non-international text chunks (tEXt and zTXt)*/ LodePNG_Text text; /*international text chunks (iTXt)*/ LodePNG_IText itext; /*time chunk (tIME)*/ unsigned char time_defined; /*if 0, no tIME chunk was or will be generated in the PNG image*/ LodePNG_Time time; /*phys chunk (pHYs)*/ unsigned phys_defined; /*is pHYs chunk defined?*/ unsigned phys_x; unsigned phys_y; unsigned char phys_unit; /*may be 0 (unknown unit) or 1 (metre)*/ #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS /*unknown chunks*/ LodePNG_UnknownChunks unknown_chunks; #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ } LodePNG_InfoPng; void LodePNG_InfoPng_init(LodePNG_InfoPng* info); void LodePNG_InfoPng_cleanup(LodePNG_InfoPng* info); unsigned LodePNG_InfoPng_copy(LodePNG_InfoPng* dest, const LodePNG_InfoPng* source); typedef struct LodePNG_InfoRaw /*contains user-chosen information about the raw image data, which is independent of the PNG image*/ { LodePNG_InfoColor color; } LodePNG_InfoRaw; void LodePNG_InfoRaw_init(LodePNG_InfoRaw* info); void LodePNG_InfoRaw_cleanup(LodePNG_InfoRaw* info); unsigned LodePNG_InfoRaw_copy(LodePNG_InfoRaw* dest, const LodePNG_InfoRaw* source); /* LodePNG_convert: Converts from any color type to 24-bit or 32-bit (later maybe more supported). return value = LodePNG error code The out buffer must have (w * h * bpp + 7) / 8, where bpp is the bits per pixel of the output color type (LodePNG_InfoColor_getBpp) */ unsigned LodePNG_convert(unsigned char* out, const unsigned char* in, LodePNG_InfoColor* infoOut, LodePNG_InfoColor* infoIn, unsigned w, unsigned h); #ifdef LODEPNG_COMPILE_DECODER typedef struct LodePNG_DecodeSettings { LodeZlib_DecompressSettings zlibsettings; /*in here is the setting to ignore Adler32 checksums*/ unsigned ignoreCrc; /*ignore CRC checksums*/ unsigned color_convert; /*whether to convert the PNG to the color type you want. Default: yes*/ #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS unsigned readTextChunks; /*if false but rememberUnknownChunks is true, they're stored in the unknown chunks*/ #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ #ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS unsigned rememberUnknownChunks; /*store all bytes from unknown chunks in the InfoPng (off by default, useful for a png editor)*/ #endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/ } LodePNG_DecodeSettings; void LodePNG_DecodeSettings_init(LodePNG_DecodeSettings* settings); typedef struct LodePNG_Decoder { LodePNG_DecodeSettings settings; LodePNG_InfoRaw infoRaw; LodePNG_InfoPng infoPng; /*info of the PNG image obtained after decoding*/ unsigned error; } LodePNG_Decoder; void LodePNG_Decoder_init(LodePNG_Decoder* decoder); void LodePNG_Decoder_cleanup(LodePNG_Decoder* decoder); void LodePNG_Decoder_copy(LodePNG_Decoder* dest, const LodePNG_Decoder* source); /*decoding functions*/ /*This function allocates the out buffer and stores the size in *outsize.*/ void LodePNG_decode(LodePNG_Decoder* decoder, unsigned char** out, size_t* outsize, const unsigned char* in, size_t insize); unsigned LodePNG_decode32(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize); /*return value is error*/ #ifdef LODEPNG_COMPILE_DISK unsigned LodePNG_decode32f(unsigned char** out, unsigned* w, unsigned* h, const char* filename); #endif /*LODEPNG_COMPILE_DISK*/ void LodePNG_inspect(LodePNG_Decoder* decoder, const unsigned char* in, size_t size); /*read the png header*/ #endif /*LODEPNG_COMPILE_DECODER*/ #ifdef LODEPNG_COMPILE_ENCODER typedef struct LodePNG_EncodeSettings { LodeZlib_DeflateSettings zlibsettings; /*settings for the zlib encoder, such as window size, ...*/ unsigned autoLeaveOutAlphaChannel; /*automatically use color type without alpha instead of given one, if given image is opaque*/ unsigned force_palette; /*force creating a PLTE chunk if colortype is 2 or 6 (= a suggested palette). If colortype is 3, PLTE is _always_ created.*/ #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS unsigned add_id; /*add LodePNG version as text chunk*/ unsigned text_compression; /*encode text chunks as zTXt chunks instead of tEXt chunks, and use compression in iTXt chunks*/ #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ } LodePNG_EncodeSettings; void LodePNG_EncodeSettings_init(LodePNG_EncodeSettings* settings); typedef struct LodePNG_Encoder { LodePNG_EncodeSettings settings; LodePNG_InfoPng infoPng; /*the info specified by the user may not be changed by the encoder. The encoder will try to generate a PNG close to the given info.*/ LodePNG_InfoRaw infoRaw; /*put the properties of the input raw image in here*/ unsigned error; } LodePNG_Encoder; void LodePNG_Encoder_init(LodePNG_Encoder* encoder); void LodePNG_Encoder_cleanup(LodePNG_Encoder* encoder); void LodePNG_Encoder_copy(LodePNG_Encoder* dest, const LodePNG_Encoder* source); /*This function allocates the out buffer and stores the size in *outsize.*/ void LodePNG_encode(LodePNG_Encoder* encoder, unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h); unsigned LodePNG_encode32(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h); /*return value is error*/ #ifdef LODEPNG_COMPILE_DISK unsigned LodePNG_encode32f(const char* filename, const unsigned char* image, unsigned w, unsigned h); #endif /*LODEPNG_COMPILE_DISK*/ #endif /*LODEPNG_COMPILE_ENCODER*/ #endif /*LODEPNG_COMPILE_PNG*/ #ifdef LODEPNG_COMPILE_DISK /*free functions allowing to load and save a file from/to harddisk*/ /*This function allocates the out buffer and stores the size in *outsize.*/ unsigned LodePNG_loadFile(unsigned char** out, size_t* outsize, const char* filename); unsigned LodePNG_saveFile(const unsigned char* buffer, size_t buffersize, const char* filename); #endif /*LODEPNG_COMPILE_DISK*/ #ifdef __cplusplus //LodePNG C++ wrapper: wraps interface with destructors and std::vectors around the harder to use C version #include #include #include #ifdef LODEPNG_COMPILE_ZLIB namespace LodeZlib { #ifdef LODEPNG_COMPILE_DECODER unsigned decompress(std::vector& out, const std::vector& in, const LodeZlib_DecompressSettings& settings = LodeZlib_defaultDecompressSettings); #endif //LODEPNG_COMPILE_DECODER #ifdef LODEPNG_COMPILE_ENCODER unsigned compress(std::vector& out, const std::vector& in, const LodeZlib_DeflateSettings& settings = LodeZlib_defaultDeflateSettings); #endif //LODEPNG_COMPILE_ENCODER } #endif //LODEPNG_COMPILE_ZLIB #ifdef LODEPNG_COMPILE_PNG namespace LodePNG { #ifdef LODEPNG_COMPILE_DECODER class Decoder : public LodePNG_Decoder { public: Decoder(); ~Decoder(); void operator=(const LodePNG_Decoder& other); //decoding functions void decode(std::vector& out, const unsigned char* in, size_t insize); void decode(std::vector& out, const std::vector& in); void inspect(const unsigned char* in, size_t size); void inspect(const std::vector& in); //error checking after decoding bool hasError() const; unsigned getError() const; //convenient access to some InfoPng parameters after decoding unsigned getWidth() const; unsigned getHeight() const; unsigned getBpp(); //bits per pixel unsigned getChannels(); //amount of channels unsigned isGreyscaleType(); //is it a greyscale type? (colorType 0 or 4) unsigned isAlphaType(); //has it an alpha channel? (colorType 2 or 6) const LodePNG_DecodeSettings& getSettings() const; LodePNG_DecodeSettings& getSettings(); void setSettings(const LodePNG_DecodeSettings& info); const LodePNG_InfoPng& getInfoPng() const; LodePNG_InfoPng& getInfoPng(); void setInfoPng(const LodePNG_InfoPng& info); void swapInfoPng(LodePNG_InfoPng& info); //faster than copying with setInfoPng const LodePNG_InfoRaw& getInfoRaw() const; LodePNG_InfoRaw& getInfoRaw(); void setInfoRaw(const LodePNG_InfoRaw& info); }; //simple functions for encoding/decoding the PNG in one call (RAW image always 32-bit) unsigned decode(std::vector& out, unsigned& w, unsigned& h, const unsigned char* in, unsigned size, unsigned colorType = 6, unsigned bitDepth = 8); unsigned decode(std::vector& out, unsigned& w, unsigned& h, const std::vector& in, unsigned colorType = 6, unsigned bitDepth = 8); #ifdef LODEPNG_COMPILE_DISK unsigned decode(std::vector& out, unsigned& w, unsigned& h, const std::string& filename, unsigned colorType = 6, unsigned bitDepth = 8); #endif //LODEPNG_COMPILE_DISK #endif //LODEPNG_COMPILE_DECODER #ifdef LODEPNG_COMPILE_ENCODER class Encoder : public LodePNG_Encoder { public: Encoder(); ~Encoder(); void operator=(const LodePNG_Encoder& other); void encode(std::vector& out, const unsigned char* image, unsigned w, unsigned h); void encode(std::vector& out, const std::vector& image, unsigned w, unsigned h); //error checking after decoding bool hasError() const; unsigned getError() const; //convenient direct access to some parameters of the InfoPng void clearPalette(); void addPalette(unsigned char r, unsigned char g, unsigned char b, unsigned char a); //add 1 color to the palette #ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS void clearText(); void addText(const std::string& key, const std::string& str); //push back both texts at once void clearIText(); void addIText(const std::string& key, const std::string& langtag, const std::string& transkey, const std::string& str); #endif //LODEPNG_COMPILE_ANCILLARY_CHUNKS const LodePNG_EncodeSettings& getSettings() const; LodePNG_EncodeSettings& getSettings(); void setSettings(const LodePNG_EncodeSettings& info); const LodePNG_InfoPng& getInfoPng() const; LodePNG_InfoPng& getInfoPng(); void setInfoPng(const LodePNG_InfoPng& info); void swapInfoPng(LodePNG_InfoPng& info); //faster than copying with setInfoPng const LodePNG_InfoRaw& getInfoRaw() const; LodePNG_InfoRaw& getInfoRaw(); void setInfoRaw(const LodePNG_InfoRaw& info); }; unsigned encode(std::vector& out, const unsigned char* in, unsigned w, unsigned h, unsigned colorType = 6, unsigned bitDepth = 8); unsigned encode(std::vector& out, const std::vector& in, unsigned w, unsigned h, unsigned colorType = 6, unsigned bitDepth = 8); #ifdef LODEPNG_COMPILE_DISK unsigned encode(const std::string& filename, const unsigned char* in, unsigned w, unsigned h, unsigned colorType = 6, unsigned bitDepth = 8); unsigned encode(const std::string& filename, const std::vector& in, unsigned w, unsigned h, unsigned colorType = 6, unsigned bitDepth = 8); #endif //LODEPNG_COMPILE_DISK #endif //LODEPNG_COMPILE_ENCODER #ifdef LODEPNG_COMPILE_DISK //free functions allowing to load and save a file from/to harddisk void loadFile(std::vector& buffer, const std::string& filename); void saveFile(const std::vector& buffer, const std::string& filename); #endif //LODEPNG_COMPILE_DISK } //namespace LodePNG #endif //LODEPNG_COMPILE_PNG #endif /*end of __cplusplus wrapper*/ /* TODO: [ ] test if there are no memory leaks or security exploits - done a lot but needs to be checked often [ ] LZ77 encoder more like the one described in zlib - to make sure it's patentfree [ ] converting color to 16-bit types [ ] read all public PNG chunk types (but never let the color profile and gamma ones ever touch RGB values, that is very annoying for textures as well as images in a browser) [ ] make sure encoder generates no chunks with size > (2^31)-1 [ ] partial decoding (stream processing) [ ] let the "isFullyOpaque" function check color keys and transparent palettes too [ ] better name for the variables "codes", "codesD", "codelengthcodes", "clcl" and "lldl" [ ] check compatibility with vareous compilers - done but needs to be redone for every newer version [ ] don't stop decoding on errors like 69, 57, 58 (make warnings that the decoder stores in the error at the very end? and make some errors just let it stop with this one chunk but still do the next ones) [ ] make option to choose if the raw image with non multiple of 8 bits per scanline should have padding bits or not, if people like storing raw images that way */ #endif /* LodePNG Documentation --------------------- 0. table of contents -------------------- 1. about 1.1. supported features 1.2. features not supported 2. C and C++ version 3. A note about security! 4. simple functions 4.1 C Simple Functions 4.2 C++ Simple Functions 5. decoder 6. encoder 7. color conversions 8. info values 9. error values 10. file IO 11. chunks and PNG editing 12. compiler support 13. examples 13.1. decoder example 13.2. encoder example 14. LodeZlib 15. changes 16. contact information 1. about -------- PNG is a file format to store raster images losslessly with good compression, supporting different color types. It can be implemented in a patent-free way. LodePNG is a PNG codec according to the Portable Network Graphics (PNG) Specification (Second Edition) - W3C Recommendation 10 November 2003. The specifications used are: *) Portable Network Graphics (PNG) Specification (Second Edition): http://www.w3.org/TR/2003/REC-PNG-20031110 *) RFC 1950 ZLIB Compressed Data Format version 3.3: http://www.gzip.org/zlib/rfc-zlib.html *) RFC 1951 DEFLATE Compressed Data Format Specification ver 1.3: http://www.gzip.org/zlib/rfc-deflate.html The most recent version of LodePNG can currently be found at http://members.gamedev.net/lode/projects/LodePNG/ LodePNG works both in C (ISO C90) and C++, with a C++ wrapper that adds extra functionality. LodePNG exists out of two files: -lodepng.h: the header file for both C and C++ -lodepng.c(pp): give it the name lodepng.c or lodepng.cpp depending on your usage If you want to start using LodePNG right away without reading this doc, get the files lodepng_examples.c or lodepng_examples.cpp to see how to use it in code, or check the (smaller) examples in chapter 13 here. LodePNG is simple but only supports the basic requirements. To achieve simplicity, the following design choices were made: There are no dependencies on any external library. To decode PNGs, there's a Decoder struct or class that can convert any PNG file data into an RGBA image buffer with a single function call. To encode PNGs, there's an Encoder struct or class that can convert image data into PNG file data with a single function call. To read and write files, there are simple functions to convert the files to/from buffers in memory. This all makes LodePNG suitable for loading textures in games, demoscene productions, saving a screenshot, images in programs that require them for simple usage, ... It's less suitable for full fledged image editors, loading PNGs over network (it requires all the image data to be available before decoding can begin), life-critical systems, ... LodePNG has a standards conformant decoder and encoder, and supports the ability to make a somewhat conformant editor. 1.1. supported features ----------------------- The following features are supported by the decoder: *) decoding of PNGs with any color type, bit depth and interlace mode, to a 24- or 32-bit color raw image, or the same color type as the PNG *) encoding of PNGs, from any raw image to 24- or 32-bit color, or the same color type as the raw image *) Adam7 interlace and deinterlace for any color type *) loading the image from harddisk or decoding it from a buffer from other sources than harddisk *) support for alpha channels, including RGBA color model, translucent palettes and color keying *) zlib decompression (inflate) *) zlib compression (deflate) *) CRC32 and ADLER32 checksums *) handling of unknown chunks, allowing making a PNG editor that stores custom and unknown chunks. *) the following chunks are supported (generated/interpreted) by both encoder and decoder: IHDR: header information PLTE: color palette IDAT: pixel data IEND: the final chunk tRNS: transparency for palettized images tEXt: textual information zTXt: compressed textual information iTXt: international textual information bKGD: suggested background color pHYs: physical dimensions tIME: modification time 1.2. features not supported --------------------------- The following features are _not_ supported: *) some features needed to make a conformant PNG-Editor might be still missing. *) partial loading/stream processing. All data must be available and is processed in one call. *) The following public chunks are not supported but treated as unknown chunks by LodePNG cHRM, gAMA, iCCP, sRGB, sBIT, hIST, sPLT 2. C and C++ version -------------------- The C version uses buffers allocated with alloc instead that you need to free() yourself. On top of that, you need to use init and cleanup functions for each struct whenever using a struct from the C version to avoid exploits and memory leaks. The C++ version has constructors and destructors that take care of these things, and uses std::vectors in the interface for storing data. Both the C and the C++ version are contained in this file! The C++ code depends on the C code, the C code works on its own. These files work without modification for both C and C++ compilers because all the additional C++ code is in "#ifdef __cplusplus" blocks that make C-compilers ignore it, and the C code is made to compile both with strict ISO C90 and C++. To use the C++ version, you need to rename the source file to lodepng.cpp (instead of lodepng.c), and compile it with a C++ compiler. To use the C version, you need to rename the source file to lodepng.c (instead of lodepng.cpp), and compile it with a C compiler. 3. A note about security! ------------------------- Despite being used already and having received bug fixes whenever bugs were reported, LodePNG may still contain possible exploits. If you discover a possible exploit, please let me know, and it will be eliminated. When using LodePNG, care has to be taken with the C version of LodePNG, as well as the C-style structs when working with C++. The following conventions are used for all C-style structs: -if a struct has a corresponding init function, always call the init function when making a new one, to avoid exploits -if a struct has a corresponding cleanup function, call it before the struct disappears to avoid memory leaks -if a struct has a corresponding copy function, use the copy function instead of "=". The destination must be inited already! 4. "Simple" Functions --------------------- For the most simple usage cases of loading and saving a PNG image, there are some simple functions that do everything in 1 call (instead of you having to instantiate a struct or class). The simple versions always use 32-bit RGBA color for the raw image, but still support loading arbitrary-colortype PNG images. The later sections of this manual are devoted to the complex versions, where you can use other color types and conversions. 4.1 C Simple Functions ---------------------- The C simple functions have a "32" or "32f" in their name, and don't take a struct as parameter, unlike the non-simple ones (see more down in the documentation). unsigned LodePNG_decode32(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize); Load PNG from given buffer. As input, give an unsigned char* buffer gotten by loading the .png file and its size. As output, you get a dynamically allocated buffer of large enough size, and the width and height of the image. The buffer's size is w * h * 4. The image is in RGBA format. The return value is the error (0 if ok). You need to do free(out) after usage to clean up the memory. unsigned LodePNG_decode32f(unsigned char** out, unsigned* w, unsigned* h, const char* filename); Load PNG from disk, from file with given name. Same as decode32, except you give a filename instead of an input buffer. unsigned LodePNG_encode32(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h); Encode PNG into buffer. As input, give a image buffer of size w * h * 4, in RGBA format. As output, you get a dynamically allocated buffer and its size, which is a PNG file that can directly be saved in this form to the harddisk. The return value is the error (0 if ok). You need to do free(out) after usage to clean up the memory. unsigned LodePNG_encode32f(const char* filename, const unsigned char* image, unsigned w, unsigned h); Encode PNG into file on disk with given name. If the file exists, it's overwritten without warning! Same parameters as encode2, except the result is stored in a file instead of a dynamic buffer. 4.2 C++ Simple Functions ------------------------ For decoding a PNG there are: unsigned LodePNG::decode(std::vector& out, unsigned& w, unsigned& h, const unsigned char* in, unsigned size); unsigned LodePNG::decode(std::vector& out, unsigned& w, unsigned& h, const std::vector& in); unsigned LodePNG::decode(std::vector& out, unsigned& w, unsigned& h, const std::string& filename); These store the pixel data as 32-bit RGBA color in the out vector, and the width and height of the image in w and h. The 3 functions each have a different input type: The first as unsigned char buffer, the second as std::vector buffer, and the third allows you to give the filename in case you want to load the PNG from disk instead of from a buffer. The return value is the error (0 if ok). For encoding a PNG there are: unsigned LodePNG::encode(std::vector& out, const unsigned char* in, unsigned w, unsigned h); unsigned LodePNG::encode(std::vector& out, const std::vector& in, unsigned w, unsigned h); unsigned LodePNG::encode(const std::string& filename, const std::vector& in, unsigned w, unsigned h); unsigned LodePNG::encode(const std::string& filename, const unsigned char* in, unsigned w, unsigned h); Specify the width and height of the input image with w and h. You can choose to get the output in an std::vector or stored in a file, and the input can come from an std::vector or an unsigned char* buffer. The input buffer must be in RGBA format and the size must be w * h * 4 bytes. The first two functions append to the out buffer, they don't clear it, clear it first before encoding into a buffer that you expect to only contain this result. On the other hand, the functions that encode to a file will completely overwrite the original file without warning if it exists. The return value is the error (0 if ok). 5. Decoder ---------- This is about the LodePNG_Decoder struct in the C version, and the LodePNG::Decoder class in the C++ version. The C++ version inherits from the C struct and adds functions in the interface. The Decoder class can be used to convert a PNG image to a raw image. Usage: -in C++: declare a LodePNG::Decoder call its decode member function with the parameters described below -in C more needs to be done due to the lack of constructors and destructors: declare a LodePNG_Decoder struct call LodePNG_Decoder_init with the struct as parameter call LodePNG_Decode with the parameters described below after usage, call LodePNG_Decoder_cleanup with the struct as parameter after usage, free() the out buffer with image data that was created by the decode function The other parameters of the decode function are: *) out: this buffer will be filled with the raw image pixels *) in: pointer to the PNG image data or std::vector with the data *) size: the size of the PNG image data (not needed for std::vector version) After decoding you need to read the width and height of the image from the decoder, see further down in this manual to see how. There's also an optional function "inspect". It has the same parameters as decode except the "out" parameter. This function will read only the header chunk of the PNG image, and store the information from it in the LodePNG_InfoPng (see below). This allows knowing information about the image without decoding it. Only the header (IHDR) information is read by this, not text chunks, not the palette, ... During the decoding it's possible that an error can happen, for example if the PNG image was corrupted. To check if an error happened during the last decoding, check the value error, which is a member of the decoder struct. In the C++ version, use hasError() and getError() of the Decoder. The error codes are explained in another section. Now about colors and settings... The Decoder contains 3 components: *) LodePNG_InfoPng: it stores information about the PNG (the input) in an LodePNG_InfoPng struct, don't modify this one yourself *) Settings: you can specify a few other settings for the decoder to use *) LodePNG_InfoRaw: here you can say what type of raw image (the output) you want to get Some of the parameters described below may be inside the sub-struct "LodePNG_InfoColor color". In the C and C++ version, when using Info structs outside of the decoder or encoder, you need to use their init and cleanup functions, but normally you use the ones in the decoder that are already handled in the init and cleanup functions of the decoder itself. =LodePNG_InfoPng= This contains information such as the original color type of the PNG image, text comments, suggested background color, etc... More details about the LodePNG_InfoPng struct are in another section. Because the dimensions of the image are important, there are shortcuts to get them in the C++ version: use decoder.getWidth() and decoder.getHeight(). In the C version, use decoder.infoPng.width and decoder.infoPng.height. =LodePNG_InfoRaw= In the LodePNG_InfoRaw struct of the Decoder, you can specify which color type you want the resulting raw image to be. If this is different from the colorType of the PNG, then the decoder will automatically convert the result to your LodePNG_InfoRaw settings. Currently the following options are supported to convert to: -colorType 6, bitDepth 8: 32-bit RGBA -colorType 2, bitDepth 8: 24-bit RGB -other color types if it's exactly the same as that in the PNG image Palette of LodePNG_InfoRaw isn't used by the Decoder, when converting from palette color to palette color, the values of the pixels are left untouched so that the colors will change if the palette is different. Color key of LodePNG_InfoRaw is not used by the Decoder. If setting color_convert is false then LodePNG_InfoRaw is completely ignored, but it will be modified to match the color type of the PNG so will be overwritten. By default, 32-bit color is used for the result. =Settings= The Settings can be used to ignore the errors created by invalid CRC and Adler32 chunks, and to disable the decoding of tEXt chunks. There's also a setting color_convert, true by default. If false, no conversion is done, the resulting data will be as it was in the PNG (after decompression) and you'll have to puzzle the colors of the pixels together yourself using the color type information in the LodePNG_InfoPng. 6. Encoder ---------- This is about the LodePNG_Encoder struct in the C version, and the LodePNG::Encoder class in the C++ version. The Encoder class can be used to convert raw image data into a PNG image. The PNG part of the encoder is working good, the zlib compression part is becoming quite fine but not as good as the official zlib yet, because it's not as fast and doesn't provide an as high compression ratio. Usage: -in C++: declare a LodePNG::Encoder call its encode member function with the parameters described below -in C more needs to be done due to the lack of constructors and destructors: declare a LodePNG_Encoder struct call LodePNG_Encoder_init with the struct as parameter call LodePNG_Encode with the parameters described below after usage, call LodePNG_Encoder_cleanup with the struct as parameter after usage, free() the out buffer with PNG data that was created by the encode function The raw image given to the encoder is an unsigned char* buffer. You also have to specify the width and height of the raw image. The result is stored in a given buffer. These buffers can be unsigned char* pointers, std::vectors or dynamically allocated unsigned char* buffers that you have to free() yourself, depending on which you use. The parameters of the encode function are: *) out: in this buffer the PNG file data will be stored (it will be appended) *) in: vector of or pointer to a buffer containing the raw image *) w and h: the width and height of the raw image in pixels Make sure that the in buffer you provide, is big enough to contain w * h pixels of the color type specified by the LodePNG_InfoRaw. In the C version, you need to free() the out buffer after usage to avoid memory leaks. In the C version, you need to use the LodePNG_Encoder_init function before using the decoder, and the LodePNG_Encoder_cleanup function after using it. In the C++ version, you don't need to do this since RAII takes care of it. The encoder generates some errors but not for everything, because, unlike when decoding a PNG, when encoding one there aren't so much parameters of the input that can be corrupted. It's the responsibility of the user to make sure that all preconditions are satesfied, such as giving a correct window size, giving an existing btype, making sure the given buffer is large enough to contain an image with the given width and height and colortype, ... The encoder can generate some errors, see the section with the explanations of errors for those. Like the Decoder, the Encoder has 3 components: *) LodePNG_InfoRaw: here you say what color type of the raw image (the input) has *) Settings: you can specify a few settings for the encoder to use *) LodePNG_InfoPng: the same LodePNG_InfoPng struct as created by the Decoder. For the encoder, with this you specify how you want the PNG (the output) to be. Some of the parameters described below may be inside the sub-struct "LodePNG_InfoColor color". In the C and C++ version, when using Info structs outside of the decoder or encoder, you need to use their init and cleanup functions, but normally you use the ones in the encoder that are already handled in the init and cleanup functions of the decoder itself. =LodePNG_InfoPng= The Decoder class stores information about the PNG image in an LodePNG_InfoPng object. With the Encoder you can do the opposite: you give it an LodePNG_InfoPng object, and it'll try to match the LodePNG_InfoPng you give as close as possible in the PNG it encodes. For example in the LodePNG_InfoPng you can specify the color type you want to use, possible tEXt chunks you want the PNG to contain, etc... For an explanation of all the values in LodePNG_InfoPng see a further section. Not all PNG color types are supported by the Encoder. Note that the encoder will only TRY to match the LodePNG_InfoPng struct you give. Some things are ignored by the encoder. The width and height of LodePNG_InfoPng are ignored as well, because instead the width and height of the raw image you give in the input are used. In fact the encoder currently uses only the following settings from it: -colorType: the ones it supports -text chunks, that you can add to the LodePNG_InfoPng with "addText" -the color key, if applicable for the given color type -the palette, if you encode to a PNG with colorType 3 -the background color: it'll add a bKGD chunk to the PNG if one is given -the interlaceMethod: None (0) or Adam7 (1) When encoding to a PNG with colorType 3, the encoder will generate a PLTE chunk. If the palette contains any colors for which the alpha channel is not 255 (so there are translucent colors in the palette), it'll add a tRNS chunk. =LodePNG_InfoRaw= You specify the color type of the raw image that you give to the input here, including a possible transparent color key and palette you happen to be using in your raw image data. By default, 32-bit color is assumed, meaning your input has to be in RGBA format with 4 bytes (unsigned chars) per pixel. =Settings= The following settings are supported (some are in sub-structs): *) autoLeaveOutAlphaChannel: when this option is enabled, when you specify a PNG color type with alpha channel (not to be confused with the color type of the raw image you specify!!), but the encoder detects that all pixels of the given image are opaque, then it'll automatically use the corresponding type without alpha channel, resulting in a smaller PNG image. *) btype: the block type for LZ77. 0 = uncompressed, 1 = fixed huffman tree, 2 = dynamic huffman tree (best compression) *) useLZ77: whether or not to use LZ77 for compressed block types *) windowSize: the window size used by the LZ77 encoder (1 - 32768) *) force_palette: if colorType is 2 or 6, you can make the encoder write a PLTE chunk if force_palette is true. This can used as suggested palette to convert to by viewers that don't support more than 256 colors (if those still exist) *) add_id: add text chunk "Encoder: LodePNG " to the image. *) text_compression: default 0. If 1, it'll store texts as zTXt instead of tEXt chunks. zTXt chunks use zlib compression on the text. This gives a smaller result on large texts but a larger result on small texts (such as a single program name). It's all tEXt or all zTXt though, there's no separate setting per text yet. 7. color conversions -------------------- For trickier usage of LodePNG, you need to understand about PNG color types and about how and when LodePNG uses the settings in LodePNG_InfoPng, LodePNG_InfoRaw and Settings. =PNG color types= A PNG image can have many color types, ranging from 1-bit color to 64-bit color, as well as palettized color modes. After the zlib decompression and unfiltering in the PNG image is done, the raw pixel data will have that color type and thus a certain amount of bits per pixel. If you want the output raw image after decoding to have another color type, a conversion is done by LodePNG. The PNG specification mentions the following color types: 0: greyscale, bit depths 1, 2, 4, 8, 16 2: RGB, bit depths 8 and 16 3: palette, bit depths 1, 2, 4 and 8 4: greyscale with alpha, bit depths 8 and 16 6: RGBA, bit depths 8 and 16 Bit depth is the amount of bits per color channel. =Default Behaviour of LodePNG= By default, the Decoder will convert the data from the PNG to 32-bit RGBA color, no matter what color type the PNG has, so that the result can be used directly as a texture in OpenGL etc... without worries about what color type the original image has. The Encoder assumes by default that the raw input you give it is a 32-bit RGBA buffer and will store the PNG as either 32 bit or 24 bit depending on whether or not any translucent pixels were detected in it. To get the default behaviour, don't change the values of LodePNG_InfoRaw and LodePNG_InfoPng of the encoder, and don't change the values of LodePNG_InfoRaw of the decoder. =Color Conversions= As explained in the sections about the Encoder and Decoder, you can specify color types and bit depths in LodePNG_InfoPng and LodePNG_InfoRaw, to change the default behaviour explained above. (for the Decoder you can only specify the LodePNG_InfoRaw, because the LodePNG_InfoPng contains what the PNG file has). To avoid some confusion: -the Decoder converts from PNG to raw image -the Encoder converts from raw image to PNG -the color type and bit depth in LodePNG_InfoRaw, are those of the raw image -the color type and bit depth in LodePNG_InfoPng, are those of the PNG -if the color type of the LodePNG_InfoRaw and PNG image aren't the same, a conversion between the color types is done if the color types are supported Supported color types: -It's possible to load PNGs from any colortype and to save PNGs of any colorType. -Both encoder and decoder use the same converter. So both encoder and decoder suport the same color types at the input and the output. So the decoder supports any type of PNG image and can convert it to certain types of raw image, while the encoder supports any type of raw data but only certain color types for the output PNG. -The converter can convert from _any_ input color type, to 24-bit RGB or 32-bit RGBA -The converter can convert from greyscale input color type, to 8-bit greyscale or greyscale with alpha -If both color types are the same, conversion from anything to anything is possible -Color types that are invalid according to the PNG specification are not allowed -When converting from a type with alpha channel to one without, the alpha channel information is discarded -When converting from a type without alpha channel to one with, the result will be opaque except pixels that have the same color as the color key of the input if one was given -When converting from 16-bit bitDepth to 8-bit bitDepth, the 16-bit precision information is lost, only the most significant byte is kept -Converting from color to greyscale is not supported on purpose: choosing what kind of color to greyscale conversion to do is not a decision a PNG codec should make -Converting from/to a palette type, only keeps the indices, it ignores the colors defined in the palette No conversion needed...: -If the color type of the PNG image and raw image are the same, then no conversion is done, and all color types are supported. -In the encoder, you can make it save a PNG with any color by giving the LodePNG_InfoRaw and LodePNG_InfoPng the same color type. -In the decoder, you can make it store the pixel data in the same color type as the PNG has, by setting the color_convert setting to false. Settings in infoRaw are then ignored. The function LodePNG_convert does this, which is available in the interface but normally isn't needed since the encoder and decoder already call it. =More Notes= In the PNG file format, if a less than 8-bit per pixel color type is used and the scanlines have a bit amount that isn't a multiple of 8, then padding bits are used so that each scanline starts at a fresh byte. However: The input image you give to the encoder, and the output image you get from the decoder will NOT have these padding bits in that case, e.g. in the case of a 1-bit image with a width of 7 pixels, the first pixel of the second scanline will the the 8th bit of the first byte, not the first bit of a new byte. 8. info values -------------- Both the encoder and decoder use a variable of type LodePNG_InfoPng and LodePNG_InfoRaw, which both also contain a LodePNG_InfoColor. Here's a list of each of the values stored in them: *) info from the PNG header (IHDR chunk): width: width of the image in pixels height: height of the image in pixels colorType: color type of the original PNG file bitDepth: bits per sample compressionMethod: compression method of the original file. Always 0. filterMethod: filter method of the original file. Always 0. interlaceMethod: interlace method of the original file. 0 is no interlace, 1 is adam7 interlace. Note: width and height are only used as information of a decoded PNG image. When encoding one, you don't have to specify width and height in an LodePNG_Info struct, but you give them as parameters of the encode function. The rest of the LodePNG_Info struct IS used by the encoder though! *) palette: This is a dynamically allocated unsigned char array with the colors of the palette. The value palettesize indicates the amount of colors in the palette. The allocated size of the buffer is 4 * palettesize bytes, because there are 4 values per color: R, G, B and A. Even if less color channels are used, the palette is always in RGBA format, in the order RGBARGBARGBA..... When encoding a PNG, to store your colors in the palette of the LodePNG_InfoRaw, first use LodePNG_InfoColor_clearPalette, then for each color use LodePNG_InfoColor_addPalette. In the C++ version the Encoder class also has the above functions available directly in its interface. Note that the palette information from the tRNS chunk is also already included in this palette vector. If you encode an image with palette, don't forget that you have to set the alpha channels (A) of the palette too, set them to 255 for an opaque palette. If you leave them at zero, the image will be encoded as fully invisible. This both for the palette in the infoRaw and the infoPng if the png is to have a palette. *) transparent color key key_defined: is a transparent color key given? key_r: red/greyscale component of color key key_g: green component of color key key_b: blue component of color key For greyscale PNGs, r, g and b will all 3 be set to the same. This color is 8-bit for 8-bit PNGs, 16-bit for 16-bit per channel PNGs. *) suggested background color background_defined: is a suggested background color given? background_r: red component of sugg. background color background_g: green component of sugg. background color background_b: blue component of sugg. background color This color is 8-bit for 8-bit PNGs, 16-bit for 16-bit PNGs For greyscale PNGs, r, g and b will all 3 be set to the same. When encoding the encoder writes the red one away. For palette PNGs: When decoding, the RGB value will be stored, no a palette index. But when encoding, specify the index of the palette in background_r, the other two are then ignored. The decoder pretty much ignores this background color, after all if you make a PNG translucent normally you intend it to be used against any background, on websites, as translucent textures in games, ... But you can get the color this way if needed. *) text and itext Non-international text: -text.keys: a char** buffer containing the keywords (see below) -text.strings: a char** buffer containing the texts (see below) -text.num: the amount of texts in the above char** buffers (there may be more texts in itext) -LodePNG_InfoText_clearText: use this to clear the texts again after you filled them in -LodePNG_InfoText_addText: this function is used to push back a keyword and text International text: This is stored in separate arrays! The sum text.num and itext.num is the real amount of texts. -itext.keys: keyword in English -itext.langtags: ISO 639 letter code for the language -itext.transkeys: keyword in this language -itext.strings: the text in this language, in UTF-8 -itext.num: the amount of international texts in this PNG -LodePNG_InfoIText_clearText: use this to clear the itexts again after you filled them in -LodePNG_InfoIText_addText: this function is used to push back all 4 parts of an itext Don't allocate these text buffers yourself. Use the init/cleanup functions correctly and use addText and clearText. In the C++ version the Encoder class also has the above functions available directly in its interface. The char** buffers are used like the argv parameter of a main() function, and (i)text.num takes the role of argc. In a text, there must be as much keys as strings because they always form pairs. In an itext, there must always be as much keys, langtags, transkeys and strings. They keyword of text chunks gives a short description what the actual text represents. There are a few standard standard keywords recognised by many programs: Title, Author, Description, Copyright, Creation Time, Software, Disclaimer, Warning, Source, Comment. It's allowed to use other keys. The keyword is minimum 1 character and maximum 79 characters long. It's discouraged to use a single line length longer than 79 characters for texts. *) additional color info These functions are available with longer names in the C version, and directly in the Decoder's interface in the C++ version. getBpp(): bits per pixel of the PNG image getChannels(): amount of color channels of the PNG image isGreyscaleType(): it's color type 0 or 4 isAlphaType(): it's color type 2 or 6 These values are calculated out of color type and bit depth of InfoColor. The difference between bits per pixel and bit depth is that bit depth is the number of bits per color channel, while a pixel can have multiple channels. *) pHYs chunk (image dimensions) phys_defined: if 0, there is no pHYs chunk and the values are undefined, if 1 else there is one phys_x: pixels per unit in x direction phys_y: pixels per unit in y direction phys_unit: the unit, 0 is no unit (x and y only give the ratio), 1 is metre *) tIME chunk (modification time) time_defined: if 0, there is no tIME chunk and the values are undefined, if 1 there is one time: this struct contains year as a 2-byte number (0-65535), month, day, hour, minute, second as 1-byte numbers that must be in the correct range Note: to make the encoder add a time chunk, set time_defined to 1 and fill in the correct values in all the time parameters, LodePNG will not fill the current time in these values itself, all it does is copy them over into the chunk bytes. 9. error values --------------- The meanings of the LodePNG error values: *) 0: no error, everything went ok *) 1: the Encoder/Decoder has done nothing yet, so error checking makes no sense yet *) 10: while huffman decoding: end of input memory reached without endcode *) 11: while huffman decoding: error in code tree made it jump outside of tree *) 13: problem while processing dynamic deflate block *) 14: problem while processing dynamic deflate block *) 15: problem while processing dynamic deflate block *) 16: unexisting code while processing dynamic deflate block *) 17: while inflating: end of out buffer memory reached *) 18: while inflating: invalid distance code *) 19: while inflating: end of out buffer memory reached *) 20: invalid deflate block BTYPE encountered while decoding *) 21: NLEN is not ones complement of LEN in a deflate block *) 22: while inflating: end of out buffer memory reached. This can happen if the inflated deflate data is longer than the amount of bytes required to fill up all the pixels of the image, given the color depth and image dimensions. Something that doesn't happen in a normal, well encoded, PNG image. *) 23: while inflating: end of in buffer memory reached *) 24: invalid FCHECK in zlib header *) 25: invalid compression method in zlib header *) 26: FDICT encountered in zlib header while it's not used for PNG *) 27: PNG file is smaller than a PNG header *) 28: incorrect PNG signature (the first 8 bytes of the PNG file) Maybe it's not a PNG, or a PNG file that got corrupted so that the header indicates the corruption. *) 29: first chunk is not the header chunk *) 30: chunk length too large, chunk broken off at end of file *) 31: illegal PNG color type or bpp *) 32: illegal PNG compression method *) 33: illegal PNG filter method *) 34: illegal PNG interlace method *) 35: chunk length of a chunk is too large or the chunk too small *) 36: illegal PNG filter type encountered *) 37: illegal bit depth for this color type given *) 38: the palette is too big (more than 256 colors) *) 39: more palette alpha values given in tRNS, than there are colors in the palette *) 40: tRNS chunk has wrong size for greyscale image *) 41: tRNS chunk has wrong size for RGB image *) 42: tRNS chunk appeared while it was not allowed for this color type *) 43: bKGD chunk has wrong size for palette image *) 44: bKGD chunk has wrong size for greyscale image *) 45: bKGD chunk has wrong size for RGB image *) 46: value encountered in indexed image is larger than the palette size (bitdepth == 8). Is the palette too small? *) 47: value encountered in indexed image is larger than the palette size (bitdepth < 8). Is the palette too small? *) 48: the input data is empty. Maybe a PNG file you tried to load doesn't exist or is in the wrong path. *) 49: jumped past memory while generating dynamic huffman tree *) 50: jumped past memory while generating dynamic huffman tree *) 51: jumped past memory while inflating huffman block *) 52: jumped past memory while inflating *) 53: size of zlib data too small *) 55: jumped past tree while generating huffman tree, this could be when the tree will have more leaves than symbols after generating it out of the given lenghts. They call this an oversubscribed dynamic bit lengths tree in zlib. *) 56: given output image colorType or bitDepth not supported for color conversion *) 57: invalid CRC encountered (checking CRC can be disabled) *) 58: invalid ADLER32 encountered (checking ADLER32 can be disabled) *) 59: conversion to unexisting or unsupported color type or bit depth requested by encoder or decoder *) 60: invalid window size given in the settings of the encoder (must be 0-32768) *) 61: invalid BTYPE given in the settings of the encoder (only 0, 1 and 2 are allowed) *) 62: conversion from non-greyscale color to greyscale color requested by encoder or decoder. LodePNG leaves the choice of RGB to greyscale conversion formula to the user. *) 63: length of a chunk too long, max allowed for PNG is 2147483647 bytes per chunk (2^31-1) *) 64: the length of the "end" symbol 256 in the Huffman tree is 0, resulting in the inability of a deflated block to ever contain an end code. It must be at least 1. *) 66: the length of a text chunk keyword given to the encoder is longer than the maximum 79 bytes. *) 67: the length of a text chunk keyword given to the encoder is smaller than the minimum 1 byte. *) 68: tried to encode a PLTE chunk with a palette that has less than 1 or more than 256 colors *) 69: unknown chunk type with "critical" flag encountered by the decoder *) 71: unexisting interlace mode given to encoder (must be 0 or 1) *) 72: while decoding, unexisting compression method encountering in zTXt or iTXt chunk (it must be 0) *) 73: invalid tIME chunk size *) 74: invalid pHYs chunk size *) 75: no null termination char found while decoding any kind of text chunk, or wrong length *) 76: iTXt chunk too short to contain required bytes *) 77: integer overflow in buffer size happened somewhere *) 78: file doesn't exist or couldn't be opened for reading *) 79: file couldn't be opened for writing *) 80: tried creating a tree for 0 symbols *) 9900-9999: out of memory while allocating chunk of memory somewhere 10. file IO ----------- For cases where you want to load the PNG image from a file, you can use your own file loading code, or the file loading and saving functions provided with LodePNG. These use the same unsigned char format used by the Decoder and Encoder. The loadFile function fills the given buffer up with the file from harddisk with the given name. The saveFile function saves the contents of the given buffer to the file with given name. Warning: this overwrites the contents that were previously in the file if it already existed, without warning. Note that you don't have to decode a PNG image from a file, you can as well retrieve the buffer another way in your code, because the decode function takes a buffer as parameter, not a filename. Both C and C++ versions of the loadFile and saveFile functions are available. For the C version of loadFile, you need to free() the buffer after use. The C++ versions use std::vectors so they clean themselves automatically. 11. chunks and PNG editing -------------------------- If you want to add extra chunks to a PNG you encode, or use LodePNG for a PNG editor that should follow the rules about handling of unknown chunks, or if you program is able to read other types of chunks than the ones handled by LodePNG, then that's possible with the chunk functions of LodePNG. A PNG chunk has the following layout: 4 bytes length 4 bytes type name length bytes data 4 bytes CRC 11.1 iterating through chunks ----------------------------- If you have a buffer containing the PNG image data, then the first chunk (the IHDR chunk) starts at byte number 8 of that buffer. The first 8 bytes are the signature of the PNG and are not part of a chunk. But if you start at byte 8 then you have a chunk, and can check the following things of it. NOTE: none of these functions check for memory buffer boundaries. To avoid exploits, always make sure the buffer contains all the data of the chunks. When using LodePNG_chunk_next, make sure the returned value is within the allocated memory. unsigned LodePNG_chunk_length(const unsigned char* chunk): Get the length of the chunk's data. The total chunk length is this length + 12. void LodePNG_chunk_type(char type[5], const unsigned char* chunk): unsigned char LodePNG_chunk_type_equals(const unsigned char* chunk, const char* type): Get the type of the chunk or compare if it's a certain type unsigned char LodePNG_chunk_critical(const unsigned char* chunk): unsigned char LodePNG_chunk_private(const unsigned char* chunk): unsigned char LodePNG_chunk_safetocopy(const unsigned char* chunk): Check if the chunk is critical in the PNG standard (only IHDR, PLTE, IDAT and IEND are). Check if the chunk is private (public chunks are part of the standard, private ones not). Check if the chunk is safe to copy. If it's not, then, when modifying data in a critical chunk, unsafe to copy chunks of the old image may NOT be saved in the new one if your program doesn't handle that type of unknown chunk. unsigned char* LodePNG_chunk_data(unsigned char* chunk): const unsigned char* LodePNG_chunk_data_const(const unsigned char* chunk): Get a pointer to the start of the data of the chunk. unsigned LodePNG_chunk_check_crc(const unsigned char* chunk): void LodePNG_chunk_generate_crc(unsigned char* chunk): Check if the crc is correct or generate a correct one. unsigned char* LodePNG_chunk_next(unsigned char* chunk): const unsigned char* LodePNG_chunk_next_const(const unsigned char* chunk): Iterate to the next chunk. This works if you have a buffer with consecutive chunks. Note that these functions do no boundary checking of the allocated data whatsoever, so make sure there is enough data available in the buffer to be able to go to the next chunk. unsigned LodePNG_append_chunk(unsigned char** out, size_t* outlength, const unsigned char* chunk): unsigned LodePNG_create_chunk(unsigned char** out, size_t* outlength, unsigned length, const char* type, const unsigned char* data): These functions are used to create new chunks that are appended to the data in *out that has length *outlength. The append function appends an existing chunk to the new data. The create function creates a new chunk with the given parameters and appends it. Type is the 4-letter name of the chunk. 11.2 chunks in infoPng ---------------------- The LodePNG_InfoPng struct contains a struct LodePNG_UnknownChunks in it. This struct has 3 buffers (each with size) to contain 3 types of unknown chunks: the ones that come before the PLTE chunk, the ones that come between the PLTE and the IDAT chunks, and the ones that come after the IDAT chunks. It's necessary to make the distionction between these 3 cases because the PNG standard forces to keep the ordering of unknown chunks compared to the critical chunks, but does not force any other ordering rules. infoPng.unknown_chunks.data[0] is the chunks before PLTE infoPng.unknown_chunks.data[1] is the chunks after PLTE, before IDAT infoPng.unknown_chunks.data[2] is the chunks after IDAT The chunks in these 3 buffers can be iterated through and read by using the same way described in the previous subchapter. When using the decoder to decode a PNG, you can make it store all unknown chunks if you set the option settings.rememberUnknownChunks to 1. By default, this option is off and is 0. The encoder will always encode unknown chunks that are stored in the infoPng. If you need it to add a particular chunk that isn't known by LodePNG, you can use LodePNG_append_chunk or LodePNG_create_chunk to the chunk data in infoPng.unknown_chunks.data[x]. Chunks that are known by LodePNG should not be added in that way. E.g. to make LodePNG add a bKGD chunk, set background_defined to true and add the correct parameters there and LodePNG will generate the chunk. 12. compiler support -------------------- No libraries other than the current standard C library are needed to compile LodePNG. For the C++ version, only the standard C++ library is needed on top. Add the files lodepng.c(pp) and lodepng.h to your project, include lodepng.h where needed, and your program can read/write PNG files. Use optimization! For both the encoder and decoder, compiling with the best optimizations makes a large difference. Make sure that LodePNG is compiled with the same compiler of the same version and with the same settings as the rest of the program, or the interfaces with std::vectors and std::strings in C++ can be incompatible resulting in bad things. CHAR_BITS must be 8 or higher, because LodePNG uses unsigned chars for octets. *) gcc and g++ LodePNG is developed in gcc so this compiler is natively supported. It gives no warnings with compiler options "-Wall -Wextra -pedantic -ansi", with gcc and g++ version 4.2.2 on Linux. *) Mingw and Bloodshed DevC++ The Mingw compiler (a port of gcc) used by Bloodshed DevC++ for Windows is fully supported by LodePNG. *) Visual Studio 2005 and Visual C++ 2005 Express Edition Versions 20070604 up to 20080107 have been tested on VS2005 and work. There are no warnings, except two warnings about 'fopen' being deprecated. 'fopen' is a function required by the C standard, so this warning is the fault of VS2005, it's nice of them to enforce secure code, however the multiplatform LodePNG can't follow their non-standard extensions. LodePNG is fully ISO C90 compliant. If you're using LodePNG in VS2005 and don't want to see the deprecated warnings, put this on top of lodepng.h before the inclusions: #define _CRT_SECURE_NO_DEPRECATE *) Visual Studio 6.0 The C++ version of LodePNG was not supported by Visual Studio 6.0 because Visual Studio 6.0 doesn't follow the C++ standard and implements it incorrectly. The current C version of LodePNG has not been tested in VS6 but may work now. *) Comeau C/C++ Vesion 20070107 compiles without problems on the Comeau C/C++ Online Test Drive at http://www.comeaucomputing.com/tryitout in both C90 and C++ mode. *) Compilers on Macintosh I'd love to support Macintosh but don't have one available to test it on. If it doesn't work with your compiler, maybe it can be gotten to work with the gcc compiler for Macintosh. Someone reported that it doesn't work well at all for Macintosh. All information on attempts to get it to work on Mac is welcome. *) Other Compilers If you encounter problems on other compilers, I'm happy to help out make LodePNG support the compiler if it supports the ISO C90 and C++ standard well enough. If the required modification to support the compiler requires using non standard or lesser C/C++ code or headers, I won't support it. 13. examples ------------ This decoder and encoder example show the most basic usage of LodePNG (using the classes, not the simple functions, which would be trivial) More complex examples can be found in: -lodepng_examples.c: 9 different examples in C, such as showing the image with SDL, ... -lodepng_examples.cpp: the exact same examples in C++ using the C++ wrapper of LodePNG 13.1. decoder C++ example ------------------------- //////////////////////////////////////////////////////////////////////////////// #include "lodepng.h" #include int main(int argc, char *argv[]) { const char* filename = argc > 1 ? argv[1] : "test.png"; //load and decode std::vector buffer, image; LodePNG::loadFile(buffer, filename); //load the image file with given filename LodePNG::Decoder decoder; decoder.decode(image, buffer.size() ? &buffer[0] : 0, (unsigned)buffer.size()); //decode the png //if there's an error, display it if(decoder.hasError()) std::cout << "error: " << decoder.getError() << std::endl; //the pixels are now in the vector "image", use it as texture, draw it, ... } //alternative version using the "simple" function int main(int argc, char *argv[]) { const char* filename = argc > 1 ? argv[1] : "test.png"; //load and decode std::vector image; unsigned w, h; unsigned error = LodePNG::decode(image, w, h, filename); //if there's an error, display it if(error != 0) std::cout << "error: " << error << std::endl; //the pixels are now in the vector "image", use it as texture, draw it, ... } //////////////////////////////////////////////////////////////////////////////// 13.2 encoder C++ example ------------------------ //////////////////////////////////////////////////////////////////////////////// #include "lodepng.h" #include int main(int argc, char *argv[]) { //check if user gave a filename if(argc <= 1) { std::cout << "please provide a filename to save to\n"; return 0; } //generate some image std::vector image; image.resize(512 * 512 * 4); for(unsigned y = 0; y < 512; y++) for(unsigned x = 0; x < 512; x++) { image[4 * 512 * y + 4 * x + 0] = 255 * !(x & y); image[4 * 512 * y + 4 * x + 1] = x ^ y; image[4 * 512 * y + 4 * x + 2] = x | y; image[4 * 512 * y + 4 * x + 3] = 255; } //encode and save std::vector buffer; LodePNG::Encoder encoder; encoder.encode(buffer, image, 512, 512); LodePNG::saveFile(buffer, argv[1]); //the same as the 4 lines of code above, but in 1 call: //LodePNG::encode(argv[1], image, 512, 512); } //////////////////////////////////////////////////////////////////////////////// 13.3 Decoder C example ---------------------- This example loads the PNG in 1 function call #include "lodepng.h" int main(int argc, char *argv[]) { unsigned error; unsigned char* image; size_t w, h; if(argc <= 1) return 0; error = LodePNG_decode3(&image, &w, &h, filename); free(image); } 14. LodeZlib ------------ Also available in the interface is LodeZlib. Both C and C++ versions of these functions are available. The interface is similar to that of the "simple" PNG encoding and decoding functions. LodeZlib can be used to zlib compress and decompress a buffer. It cannot be used to create gzip files however. Also, it only supports the part of zlib that is required for PNG, it does not support compression and decompression with dictionaries. 15. changes ----------- The version number of LodePNG is the date of the change given in the format yyyymmdd. Some changes aren't backwards compatible. Those are indicated with a (!) symbol. *) 02 sep 2008: fixed bug where it could create empty tree that linux apps could read by ignoring the problem but windows apps couldn't. *) 06 jun 2008: added more error checks for out of memory cases. *) 26 apr 2008: added a few more checks here and there to ensure more safety. *) 06 mar 2008: crash with encoding of strings fixed *) 02 feb 2008: support for international text chunks added (iTXt) *) 23 jan 2008: small cleanups, and #defines to divide code in sections *) 20 jan 2008: support for unknown chunks allowing using LodePNG for an editor. *) 18 jan 2008: support for tIME and pHYs chunks added to encoder and decoder. *) 17 jan 2008: ability to encode and decode compressed zTXt chunks added Also vareous fixes, such as in the deflate and the padding bits code. *) 13 jan 2008: Added ability to encode Adam7-interlaced images. Improved filtering code of encoder. *) 07 jan 2008: (!) changed LodePNG to use ISO C90 instead of C++. A C++ wrapper around this provides an interface almost identical to before. Having LodePNG be pure ISO C90 makes it more portable. The C and C++ code are together in these files but it works both for C and C++ compilers. *) 29 dec 2007: (!) changed most integer types to unsigned int + other tweaks *) 30 aug 2007: bug fixed which makes this Borland C++ compatible *) 09 aug 2007: some VS2005 warnings removed again *) 21 jul 2007: deflate code placed in new namespace separate from zlib code *) 08 jun 2007: fixed bug with 2- and 4-bit color, and small interlaced images *) 04 jun 2007: improved support for Visual Studio 2005: crash with accessing invalid std::vector element [0] fixed, and level 3 and 4 warnings removed *) 02 jun 2007: made the encoder add a tag with version by default *) 27 may 2007: zlib and png code separated (but still in the same file), simple encoder/decoder functions added for more simple usage cases *) 19 may 2007: minor fixes, some code cleaning, new error added (error 69), moved some examples from here to lodepng_examples.cpp *) 12 may 2007: palette decoding bug fixed *) 24 apr 2007: changed the license from BSD to the zlib license *) 11 mar 2007: very simple addition: ability to encode bKGD chunks. *) 04 mar 2007: (!) tEXt chunk related fixes, and support for encoding palettized PNG images. Plus little interface change with palette and texts. *) 03 mar 2007: Made it encode dynamic Huffman shorter with repeat codes. Fixed a bug where the end code of a block had length 0 in the Huffman tree. *) 26 feb 2007: Huffman compression with dynamic trees (BTYPE 2) now implemented and supported by the encoder, resulting in smaller PNGs at the output. *) 27 jan 2007: Made the Adler-32 test faster so that a timewaste is gone. *) 24 jan 2007: gave encoder an error interface. Added color conversion from any greyscale type to 8-bit greyscale with or without alpha. *) 21 jan 2007: (!) Totally changed the interface. It allows more color types to convert to and is more uniform. See the manual for how it works now. *) 07 jan 2007: Some cleanup & fixes, and a few changes over the last days: encode/decode custom tEXt chunks, separate classes for zlib & deflate, and at last made the decoder give errors for incorrect Adler32 or Crc. *) 01 jan 2007: Fixed bug with encoding PNGs with less than 8 bits per channel. *) 29 dec 2006: Added support for encoding images without alpha channel, and cleaned out code as well as making certain parts faster. *) 28 dec 2006: Added "Settings" to the encoder. *) 26 dec 2006: The encoder now does LZ77 encoding and produces much smaller files now. Removed some code duplication in the decoder. Fixed little bug in an example. *) 09 dec 2006: (!) Placed output parameters of public functions as first parameter. Fixed a bug of the decoder with 16-bit per color. *) 15 okt 2006: Changed documentation structure *) 09 okt 2006: Encoder class added. It encodes a valid PNG image from the given image buffer, however for now it's not compressed. *) 08 sep 2006: (!) Changed to interface with a Decoder class *) 30 jul 2006: (!) LodePNG_InfoPng , width and height are now retrieved in different way. Renamed decodePNG to decodePNGGeneric. *) 29 jul 2006: (!) Changed the interface: image info is now returned as a struct of type LodePNG::LodePNG_Info, instead of a vector, which was a bit clumsy. *) 28 jul 2006: Cleaned the code and added new error checks. Corrected terminology "deflate" into "inflate". *) 23 jun 2006: Added SDL example in the documentation in the header, this example allows easy debugging by displaying the PNG and its transparency. *) 22 jun 2006: (!) Changed way to obtain error value. Added loadFile function for convenience. Made decodePNG32 faster. *) 21 jun 2006: (!) Changed type of info vector to unsigned. Changed position of palette in info vector. Fixed an important bug that happened on PNGs with an uncompressed block. *) 16 jun 2006: Internally changed unsigned into unsigned where needed, and performed some optimizations. *) 07 jun 2006: (!) Renamed functions to decodePNG and placed them in LodePNG namespace. Changed the order of the parameters. Rewrote the documentation in the header. Renamed files to lodepng.cpp and lodepng.h *) 22 apr 2006: Optimized and improved some code *) 07 sep 2005: (!) Changed to std::vector interface *) 12 aug 2005: Initial release 16. contact information ----------------------- Feel free to contact me with suggestions, problems, comments, ... concerning LodePNG. If you encounter a PNG image that doesn't work properly with this decoder, feel free to send it and I'll use it to find and fix the problem. My email address is (puzzle the account and domain together with an @ symbol): Domain: gmail dot com. Account: lode dot vandevenne. Copyright (c) 2005-2008 Lode Vandevenne */ passage-4+dfsg1.orig/minorGems/graphics/converters/PNGImageConverter.cpp0000640000175000017500000003574611374544330025171 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 passage-4+dfsg1.orig/minorGems/graphics/ImageConverter.h0000640000175000017500000000263310711714511022056 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 passage-4+dfsg1.orig/minorGems/graphics/getMouse.h0000640000175000017500000000034207205611501020726 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 );passage-4+dfsg1.orig/minorGems/graphics/keyCodes.h0000640000175000017500000000104407205611501020704 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 #endifpassage-4+dfsg1.orig/minorGems/graphics/linux/0000750000175000017500000000000011376536643020145 5ustar pabspabspassage-4+dfsg1.orig/minorGems/graphics/linux/SDLTest.cpp0000640000175000017500000001173007274131037022124 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); */ } passage-4+dfsg1.orig/minorGems/graphics/linux/ScreenGraphicsLinux.cpp0000640000175000017500000000660310447741000024556 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 ); } passage-4+dfsg1.orig/minorGems/graphics/linux/graphixCommonDefs.h0000640000175000017500000000013007205611501023705 0ustar pabspabs// ALifeGUICommonDefs.h // common definitions for ALifeGui #define LINUX_KEY_CODES passage-4+dfsg1.orig/minorGems/graphics/Image.h0000640000175000017500000003775011070202762020175 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 passage-4+dfsg1.orig/minorGems/graphics/ImageColorConverter.h0000640000175000017500000003377607353715726023112 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 passage-4+dfsg1.orig/minorGems/graphics/mac/0000750000175000017500000000000011376536643017546 5ustar pabspabspassage-4+dfsg1.orig/minorGems/graphics/mac/graphixCommonDefs.h0000640000175000017500000000012507205611502023313 0ustar pabspabs// ALifeGUICommonDefs.h // common definitions for ALifeGui #define MAC_KEY_CODESpassage-4+dfsg1.orig/minorGems/graphics/mac/graphixFramework.cpp0000640000175000017500000001727507205611502023567 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 cant 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. Dont 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. } passage-4+dfsg1.orig/minorGems/graphics/win32/0000750000175000017500000000000011376536644017751 5ustar pabspabspassage-4+dfsg1.orig/minorGems/graphics/win32/graphixCommonDefs.h0000640000175000017500000000013107205611501023511 0ustar pabspabs// ALifeGUICommonDefs.h // common definitions for ALifeGui #define WINDOWS_KEY_CODESpassage-4+dfsg1.orig/minorGems/graphics/win32/graphixFramework.cpp0000640000175000017500000002651507205611501023765 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 passage-4+dfsg1.orig/minorGems/graphics/loadfile.h0000640000175000017500000000025307205611501020716 0ustar pabspabsvoid loadFile( const char* fileName, long sizeInBytes, unsigned char* byteDestPtr); void loadRawFile( const char* fileName, long sizeInBytes, unsigned char* byteDestPtr);passage-4+dfsg1.orig/minorGems/graphics/test/0000750000175000017500000000000011376536644017766 5ustar pabspabspassage-4+dfsg1.orig/minorGems/graphics/test/tgaConverter.cpp0000640000175000017500000001002007353716210023114 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; } passage-4+dfsg1.orig/minorGems/graphics/test/yiq2rgb.cpp0000640000175000017500000000622207353474230022044 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; } passage-4+dfsg1.orig/minorGems/graphics/test/rgb2yiq.cpp0000640000175000017500000000615707353474230022053 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; } passage-4+dfsg1.orig/minorGems/graphics/test/tgaConverterCompile0000750000175000017500000000014107353716210023651 0ustar pabspabsg++ -g -o tgaConverter -I../../.. tgaConverter.cpp ../../../minorGems/io/file/linux/PathLinux.cpppassage-4+dfsg1.orig/minorGems/graphics/test/rgb2yiqCompile0000750000175000017500000000012407352467255022601 0ustar pabspabsg++ -o rgb2yiq -I../../.. rgb2yiq.cpp ../../../minorGems/io/file/linux/PathLinux.cpppassage-4+dfsg1.orig/minorGems/graphics/test/yiq2rgbCompile0000750000175000017500000000012707352505010022562 0ustar pabspabsg++ -g -o yiq2rgb -I../../.. yiq2rgb.cpp ../../../minorGems/io/file/linux/PathLinux.cpppassage-4+dfsg1.orig/minorGems/numtest.cpp0000640000175000017500000000135507237350067017411 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; } passage-4+dfsg1.orig/minorGems/system/0000750000175000017500000000000011376536650016530 5ustar pabspabspassage-4+dfsg1.orig/minorGems/system/semaphoreTest.cpp0000640000175000017500000000366407234645702022066 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; } passage-4+dfsg1.orig/minorGems/system/unix/0000750000175000017500000000000011376536650017513 5ustar pabspabspassage-4+dfsg1.orig/minorGems/system/unix/LauncherUnix.cpp0000640000175000017500000000077307607633527022637 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 } } passage-4+dfsg1.orig/minorGems/system/unix/TimeUnix.cpp0000640000175000017500000000123407447774050021764 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; } passage-4+dfsg1.orig/minorGems/system/endian.h0000640000175000017500000000317111165410607020127 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 passage-4+dfsg1.orig/minorGems/system/BinarySemaphore.h0000640000175000017500000000331307722702203021757 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 passage-4+dfsg1.orig/minorGems/system/Launcher.h0000640000175000017500000000163007607633465020447 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 passage-4+dfsg1.orig/minorGems/system/Time.h0000640000175000017500000000444310202731646017572 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 passage-4+dfsg1.orig/minorGems/system/Semaphore.h0000640000175000017500000001023307777611355020632 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 passage-4+dfsg1.orig/minorGems/system/MutexLock.h0000640000175000017500000000207307554113530020606 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 passage-4+dfsg1.orig/minorGems/system/FinishedSignalThread.cpp0000640000175000017500000000203410033036772023240 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(); } passage-4+dfsg1.orig/minorGems/system/FinishedSignalThreadManager.cpp0000640000175000017500000000461510170260026024533 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(); } } passage-4+dfsg1.orig/minorGems/system/TestThread.h0000640000175000017500000000252107565075331020750 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 passage-4+dfsg1.orig/minorGems/system/StopSignalThread.cpp0000640000175000017500000000231510170267060022434 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(); } passage-4+dfsg1.orig/minorGems/system/linux/0000750000175000017500000000000011376536650017667 5ustar pabspabspassage-4+dfsg1.orig/minorGems/system/linux/ThreadLinux.cpp0000640000175000017500000001335410174541132022613 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 passage-4+dfsg1.orig/minorGems/system/linux/MutexLockLinux.cpp0000640000175000017500000000311307554122211023310 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 ); } passage-4+dfsg1.orig/minorGems/system/linux/BinarySemaphoreLinux.cpp0000640000175000017500000001103210401110426024452 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] ) ); } passage-4+dfsg1.orig/minorGems/system/FinishedSignalThread.h0000640000175000017500000000326510147345462022721 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 passage-4+dfsg1.orig/minorGems/system/FinishedSignalThreadManager.h0000640000175000017500000000273610170257606024214 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 passage-4+dfsg1.orig/minorGems/system/ThreadSafePrinter.h0000640000175000017500000000262710032526077022251 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 passage-4+dfsg1.orig/minorGems/system/Thread.h0000640000175000017500000000560710174541121020101 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 passage-4+dfsg1.orig/minorGems/system/TestThread.cpp0000640000175000017500000000231710032526430021266 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; } passage-4+dfsg1.orig/minorGems/system/StopSignalThread.h0000640000175000017500000000361610170267060022106 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 passage-4+dfsg1.orig/minorGems/system/win32/0000750000175000017500000000000011376536650017472 5ustar pabspabspassage-4+dfsg1.orig/minorGems/system/win32/ThreadWin32.cpp0000640000175000017500000000456010174541132022220 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; } passage-4+dfsg1.orig/minorGems/system/win32/BinarySemaphoreWin32.cpp0000640000175000017500000000401707722702212024101 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 ); } passage-4+dfsg1.orig/minorGems/system/win32/LauncherWin32.cpp0000640000175000017500000000065007637725606022572 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 ); } passage-4+dfsg1.orig/minorGems/system/win32/MutexLockWin32.cpp0000640000175000017500000000341107554370760022735 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 ); } passage-4+dfsg1.orig/minorGems/system/win32/TimeWin32.cpp0000640000175000017500000000447010133647061021712 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 ); } passage-4+dfsg1.orig/runToBuild0000750000175000017500000000076111376536623015265 0ustar pabspabs#!/bin/bash # # Modification History # # 2007-November-12 Jason Rohrer # Copied from Cultivation. # cd gamma256/gameSource chmod u+x ./configure ./configure echo "Building Passage..." make cd ../.. mkdir graphics mkdir music mkdir settings cp gamma256/gameSource/Passage ./Passage cp gamma256/documentation/Readme.txt . cp gamma256/gameSource/graphics/* ./graphics cp gamma256/gameSource/music/* ./music cp gamma256/gameSource/settings/* ./settings echo "Run Passage to play."