/* * * Copyright (c) 2002, 2003 Johannes Prix * * This file is part of Freedroid * * Freedroid is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Freedroid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Freedroid; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * */ /* ---------------------------------------------------------------------- * All functions that have to do with loading and saving of games. * ---------------------------------------------------------------------- */ /* * This file should not contain any german, since it originates from * a time where we didn't use german for comments any more. * */ #define _saveloadgame_c #include "system.h" #include "defs.h" #include "struct.h" #include "global.h" #include "proto.h" #include "SDL_rotozoom.h" #include "sys/stat.h" #define INFLUENCER_STRUCTURE_RAW_DATA_STRING "Now the raw data of the influencer structure:" #define ALLENEMYS_RAW_DATA_STRING "Now the raw AllEnemys data:" #define ALLBULLETS_RAW_DATA_STRING "Now the raw AllBullets data:" #define DROID001_RAW_DATA_STRING "Now the raw DROID001 data:" #define END_OF_SAVEDGAME_DATA_STRING "End of saved game data file." #define LEVELNUM_EXPL_STRING "Explicit number of the level the influ currently is in=" #define SAVEDGAME_EXT ".savegame" #define SAVE_GAME_THUMBNAIL_EXT ".thumbnail.bmp" int load_game_command_came_from_inside_running_game = FALSE ; /* ---------------------------------------------------------------------- * * * ---------------------------------------------------------------------- */ void ShowSaveLoadGameProgressMeter( int Percentage , int IsSavegame ) { SDL_Rect TargetRect; TargetRect.x = AllMousePressButtons[ SAVE_GAME_BANNER ] . button_rect . x + ( AllMousePressButtons[ SAVE_GAME_BANNER ] . button_rect . w - 100 ) / 2 + 2 ; TargetRect.y = AllMousePressButtons[ SAVE_GAME_BANNER ] . button_rect . y + 20 ; TargetRect.w = Percentage ; TargetRect.h = 20 ; if ( IsSavegame) ShowGenericButtonFromList ( SAVE_GAME_BANNER ); else ShowGenericButtonFromList ( LOAD_GAME_BANNER ); our_SDL_fill_rect_wrapper ( Screen , &TargetRect , SDL_MapRGB ( Screen->format , 0x0FF , 0x0FF , 0x0FF ) ) ; UpdateScreenOverButtonFromList ( SAVE_GAME_BANNER ); }; // void ShowSaveGameProgressMeter( int Percentage ) /* ---------------------------------------------------------------------- * * * ---------------------------------------------------------------------- */ void LoadAndShowThumbnail ( char* CoreFilename ) { char filename[1000]; SDL_Surface* NewThumbnail; SDL_Rect TargetRectangle; if ( ! our_config_dir ) return; DebugPrintf ( 2 , "\nTrying to load thumbnail for character '%s'. " , CoreFilename ); //-------------------- // First we save the full ship information, same as with the level editor // sprintf( filename , "%s/%s%s", our_config_dir , CoreFilename , SAVE_GAME_THUMBNAIL_EXT ); NewThumbnail = our_IMG_load_wrapper ( filename ); if ( NewThumbnail == NULL ) return; // TargetRectangle.x = GameConfig . screen_width - NewThumbnail ->w ; TargetRectangle.x = 10 ; TargetRectangle.y = GameConfig . screen_height - NewThumbnail ->h - 10 ; if ( use_open_gl ) swap_red_and_blue_for_open_gl ( NewThumbnail ); our_SDL_blit_surface_wrapper ( NewThumbnail , NULL , Screen , &TargetRectangle ); SDL_FreeSurface( NewThumbnail ); }; // void LoadAndShowThumbnail ( char* CoreFilename ) /* ---------------------------------------------------------------------- * * * ---------------------------------------------------------------------- */ void LoadAndShowStats ( char* CoreFilename ) { char filename[1000]; struct stat FileInfoBuffer; char InfoString[5000]; struct tm *LocalTimeSplitup; long int FileSize; char* month_names[] = { "Jan" , "Feb" , "Mar" , "Apr" , "May" , "Jun" , "Jul" , "Aug" , "Sep" , "Oct" , "Nov" , "Dec" }; if ( ! our_config_dir ) return; DebugPrintf ( 2 , "\nTrying to get file stats for character '%s'. " , CoreFilename ); //-------------------- // First we save the full ship information, same as with the level editor // sprintf( filename , "%s/%s%s", our_config_dir , CoreFilename , SAVEDGAME_EXT ); if ( stat ( filename , & ( FileInfoBuffer) ) ) { fprintf( stderr, "\n\nfilename: %s. \n" , filename ); GiveStandardErrorMessage ( __FUNCTION__ , "\ Freedroid was unable to determine the time of the last modification on\n\ your saved game file.\n\ This is either a bug in Freedroid or an indication, that the directory\n\ or file permissions of ~/.freedroid_rpg are somehow not right.", NO_NEED_TO_INFORM, IS_FATAL ); }; LocalTimeSplitup = localtime ( & ( FileInfoBuffer.st_mtime ) ) ; sprintf( InfoString , "%d %s %02d %02d:%02d" , 1900 + LocalTimeSplitup->tm_year , month_names [ LocalTimeSplitup->tm_mon ] , LocalTimeSplitup->tm_mday , LocalTimeSplitup->tm_hour , LocalTimeSplitup->tm_min ); PutString ( Screen , 240 , GameConfig . screen_height - 3 * FontHeight ( GetCurrentFont () ) , "Last Modified:" ); PutString ( Screen , 240 , GameConfig . screen_height - 2 * FontHeight ( GetCurrentFont () ) , InfoString ); //-------------------- // Now that the modification time has been set up, we can start to compute // the overall disk space of all files in question. // FileSize = FileInfoBuffer.st_size; //-------------------- // The saved ship must exist. On not, it's a sever error! // sprintf( filename , "%s/%s%s", our_config_dir , CoreFilename , ".shp" ); if ( stat ( filename , & ( FileInfoBuffer) ) ) { fprintf( stderr, "\n\nfilename: %s. \n" , filename ); GiveStandardErrorMessage ( __FUNCTION__ , "\ Freedroid was unable to determine the time of the last modification on\n\ your saved game file.\n\ This is either a bug in Freedroid or an indication, that the directory\n\ or file permissions of ~/.freedroid_rpg are somehow not right.", NO_NEED_TO_INFORM, IS_FATAL ); } FileSize += FileInfoBuffer.st_size; //-------------------- // A thumbnail may not yet exist. We won't make much fuss if it doesn't. // sprintf( filename , "%s/%s%s", our_config_dir , CoreFilename , SAVE_GAME_THUMBNAIL_EXT ); if ( ! stat ( filename , & ( FileInfoBuffer) ) ) { FileSize += FileInfoBuffer.st_size; } sprintf( InfoString , "File Size: %2.3f MB" , ((float)FileSize) / ( 1024.0 * 1024.0 ) ); // PutString ( Screen , 240 , GameConfig . screen_height - 2 * FontHeight ( GetCurrentFont () ) , "File Size:" ); PutString ( Screen , 240 , GameConfig . screen_height - 1 * FontHeight ( GetCurrentFont () ) , InfoString ); }; // void LoadAndShowStats ( char* filename ); /* ---------------------------------------------------------------------- * This function stores a thumbnail of the currently running game, so that * these thumbnails can be browsed when choosing which game to load. * ---------------------------------------------------------------------- */ void SaveThumbnailOfGame ( void ) { char filename[1000]; SDL_Surface* NewThumbnail = NULL; SDL_Surface* FullView; if ( ! our_config_dir ) return; //-------------------- // First we save the full ship information, same as with the level editor // sprintf( filename , "%s/%s%s", our_config_dir, Me [ 0 ] . character_name , SAVE_GAME_THUMBNAIL_EXT ); AssembleCombatPicture ( SHOW_ITEMS ); if ( use_open_gl ) { #ifdef HAVE_LIBGL //-------------------- // We need to make a copy in processor memory. GLvoid * imgdata = malloc ( ( GameConfig . screen_width + 2 ) * ( GameConfig . screen_height + 2 ) * 4 ); glReadPixels( 0 , 1, GameConfig . screen_width , GameConfig . screen_height-1 , GL_RGB, GL_UNSIGNED_BYTE, imgdata ); //-------------------- // Now we need to make a real SDL surface from the raw image data we // have just extracted. // FullView = SDL_CreateRGBSurfaceFrom( imgdata , GameConfig . screen_width , GameConfig . screen_height, 24, 3 * GameConfig . screen_width, 0x0FF0000, 0x0FF00, 0x0FF , 0 ); NewThumbnail = zoomSurface( FullView , 0.32 * 640.0f / GameConfig . screen_width , 0.32 * 640.0f / GameConfig . screen_width , 0 ); free ( imgdata ) ; if ( NewThumbnail == NULL ) return; //-------------------- // Of course, since we used OpenGL for generating the raw image data, the data is // upside down again. Now that won't be much of a problem, since we've already // dealt with is several times, using the following flipping code. // flip_image_horizontally ( NewThumbnail ); swap_red_and_blue_for_open_gl ( NewThumbnail ); SDL_FreeSurface ( FullView ) ; #endif } else { NewThumbnail = zoomSurface( Screen , 0.32 , 0.32 , 0 ); } SDL_SaveBMP( NewThumbnail , filename ); SDL_FreeSurface( NewThumbnail ); }; // void SaveThumbnailOfGame ( void ) /* ---------------------------------------------------------------------- * This function saves the current game of Freedroid to a file. * ---------------------------------------------------------------------- */ int SaveGame( void ) { char *SaveGameHeaderString; FILE *SaveGameFile; // to this file we will save all the ship data... char filename[1000]; char linebuf[10000]; char* MenuTexts[10]={ "Back" , "" , "" , "" , "" , "" , "" , "" , "" , "" }; if ( ! our_config_dir ) return (OK); //-------------------- // Saving might take a while, therefore we activate the conservative // frame rate, just to be sure, so that no sudden jumps occur, perhaps // placing the influencer or some bullets outside the map even! // Activate_Conservative_Frame_Computation(); DebugPrintf ( SAVE_LOAD_GAME_DEBUG , "\nint SaveGame( void ): real function call confirmed."); //-------------------- // Now we add a security question to prevent the player from (accidentially) // saving a game where his character is already dead // if ( Me[0].energy <= 0 ) { DoMenuSelection( _("\n\n Surely you do not really want do save a game \n\n where your tux is dead, do you?"), MenuTexts , 1 , -1 , NULL ); return ( OK ); } //-------------------- // Now that we really start to save the game, it's time to display the save // game progress meter... // ShowSaveLoadGameProgressMeter( 0 , TRUE ) ; //-------------------- // We must make sure the version string in the Me struct is set // correctly for later loading... // But not only the version, but also some struct sizes and array // lengthes should be checked as well, so that we have some extra // protection against saved game data not fitting into some structs // any more... // sprintf ( Me [ 0 ] . freedroid_version_string , "%s;sizeof(tux_t)=%d;sizeof(enemy)=%d;sizeof(bullet)=%d;MAXBULLETS=%d;MAX_ENEMYS_ON_SHIP=%d\n", VERSION , (int) sizeof(tux_t) , (int) sizeof(enemy) , (int) sizeof(bullet) , (int) MAXBULLETS , (int) MAX_ENEMYS_ON_SHIP ); //-------------------- sprintf( filename , "%s/%s%s", our_config_dir, Me[0].character_name, ".shp" ); if ( SaveShip( filename ) != OK ) { GiveStandardErrorMessage ( __FUNCTION__ , "\ The SAVING OF THE SHIP DATA FOR THE SAVED GAME FAILED!\n\ This is either a bug in Freedroid or an indication, that the directory\n\ or file permissions of ~/.freedroid_rpg are somehow not right.", PLEASE_INFORM, IS_FATAL ); } else { DebugPrintf( SAVE_LOAD_GAME_DEBUG , "\nShip data for saved game seems to have been saved correctly.\n"); } // ShowSaveGameProgressMeter( 30 ) ; //-------------------- // First, we must determine the save game file name // sprintf ( filename , "%s/%s%s", our_config_dir , Me[0].character_name, ".savegame"); DebugPrintf ( SAVE_LOAD_GAME_DEBUG , "\nint SaveShip(char *shipname): now opening the savegame file for writing ..."); //-------------------- // Now that we know which filename to use, we can open the save file for writing // if( ( SaveGameFile = fopen(filename, "wb")) == NULL) { printf("\n\nError opening save game file for writing...\n\nTerminating...\n\n"); Terminate(ERR); // return ERR; } //-------------------- // Now that the file is opend for writing, we can start writing. And the first thing // we will write to the file will be a fine header, indicating what this file is about // and things like that... // SaveGameHeaderString="\n\ ----------------------------------------------------------------------\n\ *\n\ * Copyright (c) 1994, 2002 Johannes Prix\n\ * Copyright (c) 1994, 2002 Reinhard Prix\n\ *\n\ *\n\ * This file is part of Freedroid\n\ *\n\ * Freedroid is free software; you can redistribute it and/or modify\n\ * it under the terms of the GNU General Public License as published by\n\ * the Free Software Foundation; either version 2 of the License, or\n\ * (at your option) any later version.\n\ *\n\ * Freedroid is distributed in the hope that it will be useful,\n\ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n\ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\ * GNU General Public License for more details.\n\ *\n\ * You should have received a copy of the GNU General Public License\n\ * along with Freedroid; see the file COPYING. If not, write to the \n\ * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, \n\ * MA 02111-1307 USA\n\ *\n\ ----------------------------------------------------------------------\n\ \n\ This file was generated using the Freedroid save level option.\n\ If you have questions concerning Freedroid, please send mail to:\n\ \n\ freedroid-discussion@lists.sourceforge.net\n\ \n"; fwrite ( SaveGameHeaderString , strlen( SaveGameHeaderString), sizeof(char), SaveGameFile); //-------------------- // Since no other information than the dynamic pointer CurLevel is available // to tell the current level number, we must write out that information explicitly // fwrite ( LEVELNUM_EXPL_STRING , strlen ( LEVELNUM_EXPL_STRING ) , sizeof(char), SaveGameFile); sprintf( linebuf , "%d\n", CurLevel->levelnum ); fwrite ( linebuf , strlen ( linebuf ) , sizeof(char), SaveGameFile); // ShowSaveGameProgressMeter( 40 ) ; // -------------------- // Now we write the influencer raw data start string out to the file and of course // then the real raw influencer data follow suit afterwards. // fwrite ( INFLUENCER_STRUCTURE_RAW_DATA_STRING , strlen( INFLUENCER_STRUCTURE_RAW_DATA_STRING ), sizeof(char), SaveGameFile ); fwrite ( &(Me) , sizeof( tux_t ) , sizeof( char ) , SaveGameFile ); // fwrite ( DROID001_RAW_DATA_STRING , strlen( DROID001_RAW_DATA_STRING ), // sizeof(char), SaveGameFile ); // fwrite ( &( Druidmap[ DRUID001 ]) , sizeof( druidspec ) , sizeof( char ) , SaveGameFile ); // ShowSaveGameProgressMeter( 50 ) ; // -------------------- // Now we write the enemy raw data start string out to the file and of course // then the real raw enemy data follow suit afterwards. // fwrite ( ALLENEMYS_RAW_DATA_STRING , strlen( ALLENEMYS_RAW_DATA_STRING ), sizeof(char), SaveGameFile ); fwrite ( &(AllEnemys) , sizeof( enemy ) * MAX_ENEMYS_ON_SHIP , sizeof( char ) , SaveGameFile ); // ShowSaveGameProgressMeter( 60 ) ; // -------------------- // Now we write the bullet raw data start string out to the file and of course // then the real raw enemy data follow suit afterwards. // fwrite ( ALLBULLETS_RAW_DATA_STRING , strlen( ALLBULLETS_RAW_DATA_STRING ), sizeof(char), SaveGameFile ); fwrite ( & ( AllBullets ) , sizeof( bullet ) * MAXBULLETS , sizeof( char ) , SaveGameFile ); // ShowSaveGameProgressMeter( 70 ) ; //-------------------- // Now that all the nescessary information has been written to the save game file // (hopefully), we can finally add the 'end of saved game file'-marker string, that // will be needed by the loading function to detect the end of the file and that the // file is really there and complete. So we add this last string to the file: // fwrite ( END_OF_SAVEDGAME_DATA_STRING , strlen( END_OF_SAVEDGAME_DATA_STRING ), sizeof(char), SaveGameFile ); if( fclose( SaveGameFile ) == EOF) { printf("\n\nClosing of save game file failed in SaveGame...\n\nTerminating\n\n"); Terminate(ERR); // return ERR; } ShowSaveLoadGameProgressMeter( 99 , TRUE ); SaveThumbnailOfGame ( ); ShowSaveLoadGameProgressMeter( 100 , TRUE ) ; append_new_game_message ( _("Game saved.") ); DebugPrintf ( SAVE_LOAD_GAME_DEBUG , "\nint SaveGame( void ): end of function reached."); return OK; }; // int SaveGame( void ) /* ---------------------------------------------------------------------- * This function loads an old saved game of Freedroid from a file. * ---------------------------------------------------------------------- */ int DeleteGame( void ) { char filename[1000]; if ( ! our_config_dir ) return (OK); //-------------------- // First we save the full ship information, same as with the level editor // sprintf( filename , "%s/%s%s", our_config_dir , Me[0].character_name, ".shp"); remove ( filename ) ; //-------------------- // First, we must determine the savedgame data file name // sprintf (filename, "%s/%s%s", our_config_dir, Me[0].character_name, SAVEDGAME_EXT); remove ( filename ); sprintf( filename , "%s/%s%s", our_config_dir, Me[0].character_name , SAVE_GAME_THUMBNAIL_EXT ); remove ( filename ); return ( OK ); }; // int DeleteGame( void ) /* ---------------------------------------------------------------------- * This function loads an old saved game of Freedroid from a file. * ---------------------------------------------------------------------- */ int LoadGame( void ) { char version_check_string[1000]; char *LoadGameData; char filename[1000]; unsigned char* InfluencerRawDataPointer; unsigned char* EnemyRawDataPointer; unsigned char* BulletRawDataPointer; int i; int current_geographics_levelnum; FILE *DataFile; if ( ! our_config_dir ) { DebugPrintf (0, "No Config-directory, cannot load any games\n"); return (OK); } DebugPrintf ( SAVE_LOAD_GAME_DEBUG , "\n%s(): function call confirmed...." , __FUNCTION__ ); //-------------------- // Loading might take a while, therefore we activate the conservative // frame rate, just to be sure, so that no sudden jumps occur, perhaps // placing the influencer or some bullets outside the map even! // Activate_Conservative_Frame_Computation(); global_ingame_mode = GLOBAL_INGAME_MODE_NORMAL ; ShowSaveLoadGameProgressMeter( 0 , FALSE ) ; //-------------------- // First we load the full ship information, same as with the level editor sprintf( filename , "%s/%s%s", our_config_dir, Me [ 0 ] . character_name, ".shp"); //-------------------- // Maybe there isn't any saved game by that name. This case must be checked for // and handled... // if ((DataFile = fopen ( filename , "rb")) == NULL ) { GiveMouseAlertWindow ( "\nW A R N I N G !\n\nFreedroidRPG was unable to locate the saved game file you requested to load.\nThis might mean that it really isn't there cause you tried to load a game without ever having saved the game before. \nThe other explanation of this error might be a severe error in FreedroidRPG.\nNothing will be done about it." ); append_new_game_message ( _("Failed to load old game.") ); return ( ERR ) ; } else { DebugPrintf ( 1 , "\nThe saved game file (.shp file) seems to be there at least....."); } LoadShip( filename ); //-------------------- // Now we must determine the savedgame data file name // sprintf (filename, "%s/%s%s", our_config_dir, Me[0].character_name, SAVEDGAME_EXT); DebugPrintf ( SAVE_LOAD_GAME_DEBUG , "\n%s(): starting to read savegame data...." , __FUNCTION__ ); //-------------------- // Now we can read the whole savegame data into memory with one big flush // LoadGameData = ReadAndMallocAndTerminateFile( filename , END_OF_SAVEDGAME_DATA_STRING ) ; DebugPrintf ( SAVE_LOAD_GAME_DEBUG , "\n%s(): starting to decode savegame data...." , __FUNCTION__ ); //-------------------- // Before we start decoding the details, we get the former level-number where the // influencer was walking and construct a new 'CurLevel' out of it. // ReadValueFromString( LoadGameData , LEVELNUM_EXPL_STRING , "%d" , ¤t_geographics_levelnum , LoadGameData + 30000 ); CurLevel = curShip.AllLevels[ current_geographics_levelnum ]; //-------------------- // Now we start decoding our new game information and fill it into the apropriate structs // We assume, that our target strings will be found, so we give 3000000 as the search area // length, since we do not know it exactly // InfluencerRawDataPointer = MyMemmem( LoadGameData , 3000000 , INFLUENCER_STRUCTURE_RAW_DATA_STRING , strlen ( INFLUENCER_STRUCTURE_RAW_DATA_STRING ) ); InfluencerRawDataPointer += strlen ( INFLUENCER_STRUCTURE_RAW_DATA_STRING ) ; memcpy( &Me , InfluencerRawDataPointer , sizeof ( tux_t ) ); InfluencerRawDataPointer += sizeof ( tux_t ); //-------------------- // Now we decode the enemy information. // We assume, that our target strings will be found, so we give 3000000 as the search area // length, since we do not know it exactly // EnemyRawDataPointer = MyMemmem( LoadGameData , 30000000 , ALLENEMYS_RAW_DATA_STRING , strlen ( ALLENEMYS_RAW_DATA_STRING ) ); EnemyRawDataPointer += strlen ( ALLENEMYS_RAW_DATA_STRING ) ; memcpy( &(AllEnemys) , EnemyRawDataPointer , sizeof ( enemy ) * MAX_ENEMYS_ON_SHIP ); //-------------------- // Now we decode the bullet information. // We assume, that our target strings will be found, so we give 10000000 as the search area // length, since we do not know it exactly // BulletRawDataPointer = MyMemmem( LoadGameData , 30000000 , ALLBULLETS_RAW_DATA_STRING , strlen ( ALLBULLETS_RAW_DATA_STRING ) ); BulletRawDataPointer += strlen ( ALLBULLETS_RAW_DATA_STRING ) ; memcpy( &(AllBullets) , BulletRawDataPointer , sizeof ( bullet ) * MAXBULLETS ); //-------------------- // When the original game was still going on, some dynamic things like pointers to some // constructed text field might have been used. Now these dynamic things somewhere in // memory of course do not exist, so any pointer previously refering to them, must be // set to acceptable values before an accident (SEGFAULT) occurs! // DebugPrintf ( SAVE_LOAD_GAME_DEBUG , "\n%s(): now correcting dangerous pointers...." , __FUNCTION__ ); Me [ 0 ] . TextToBeDisplayed = ""; for ( i = 0 ; i < MAX_ENEMYS_ON_SHIP ; i++ ) { AllEnemys[ i ].TextToBeDisplayed = "" ; AllEnemys[ i ].TextVisibleTime = 0; } for ( i = 0 ; i < MAXBULLETS ; i++ ) { //-------------------- // This might mean a slight memory loss, but I guess we can live with that... // AllBullets [ i ] . Surfaces_were_generated = FALSE; if ( AllBullets[ i ].angle_change_rate != 0 ) DeleteBullet( i , FALSE ); } //-------------------- // Now we check if the loaded game is from a compatible version of FreedroidRPG, or // if we maybe have a saved game from a different version, which would mean trouble // // NOTE: WE MUST DO THIS BEFORE ANY REFERENCE TO THE LOADED GAME IS MADE, EVEN IF // THAT REFERENCE IS SO SMALL AS TO JUST SET BACKGROUND MUSIC ACCORDING TO // CURRENT TUX POSITION IN THE MAPS AS FOUND BELOW // // // sprintf ( version_check_string , "%s;sizeof(tux_t)=%d;sizeof(enemy)=%d;sizeof(bullet)=%d;MAXBULLETS=%d;MAX_ENEMYS_ON_SHIP=%d\n", VERSION , (int) sizeof(tux_t) , (int) sizeof(enemy) , (int) sizeof(bullet) , (int) MAXBULLETS , (int) MAX_ENEMYS_ON_SHIP ); if ( strcmp ( Me [ 0 ] . freedroid_version_string , version_check_string ) != 0 ) { show_button_tooltip ( _("Error: Version or structsize mismatch! The saved game in question appears to be from a (slightly?) different version of FreedroidRPG.\nSorry, but I refuse to load it for safety/stability reasons...\nFor Recovery, a blank game will be loaded...(please disregard)\n") ); our_SDL_flip_wrapper( Screen ); while ( SpacePressed() || MouseLeftPressed() ) SDL_Delay ( 3 ); while ( !SpacePressed() && ! MouseLeftPressed() ) SDL_Delay ( 3 ); while ( SpacePressed() || MouseLeftPressed()) SDL_Delay ( 3 ); //-------------------- // Now at this point the current Tux data has been junked // around with from the failed loading attempt. We must // clear out the data and then safely exit out of the current // game! // // WARNING! If the game is already running, this really // dangerous. In that case the damaged data should best be // completely overwritten with something sensible... // (Otherwise Floating Point Exceptions and the like are likely...) // if ( load_game_command_came_from_inside_running_game ) { clear_player_inventory_and_stats ( ) ; UpdateAllCharacterStats ( 0 ) ; char fp[2048]; find_file ( "Asteroid.maps", MAP_DIR, fp, 0 ); LoadShip ( fp ) ; PrepareStartOfNewCharacter ( ) ; } return ( ERR ) ; } //-------------------- // To prevent cheating, we remove all active spells, that might still be there // from other games just played before. // clear_active_spells(); //-------------------- // Now that we have loaded the game, we must count and initialize the number // of droids used in this ship. Otherwise we might ignore some robots. // CountNumberOfDroidsOnShip ( ) ; SwitchBackgroundMusicTo( curShip.AllLevels[ Me[0].pos.z ]->Background_Song_Name ); free ( LoadGameData ); //-------------------- // Maybe someone just lost in the game and has then pressed the load // button. Then a new game is loaded and the game-over status has // to be restored as well of course. // GameOver = FALSE; DebugPrintf ( SAVE_LOAD_GAME_DEBUG , "\n%s(): end of function reached." , __FUNCTION__ ); //-------------------- // Now we know that right after loading an old saved game, the Tux might have // to 'change clothes' i.e. a lot of tux images need to be updated which can // take a little time. Therefore we print some message so the user will not // panic and push the reset button :) // PutStringFont ( Screen , FPS_Display_BFont , 75 , 150 , _("Updating Tux images (this may take a little while...)") ); our_SDL_flip_wrapper ( Screen ); //-------------------- // Now that the whole character information (and that included the automap // information) has been restored, we can use the old automap data to rebuild // the automap texture in the open_gl case... // insert_old_map_info_into_texture ( ); load_game_command_came_from_inside_running_game = TRUE ; append_new_game_message ( _("Game loaded.") ); return OK; }; // int LoadGame ( void ) #undef _saveloadgame_c