Main Page   Data Structures   File List   Data Fields   Globals   Related Pages  

nix-common/savegame_be.c

Go to the documentation of this file.
00001 
00013 #include <sys/types.h>
00014 #include <sys/stat.h>
00015 #include <sys/mman.h>
00016 #include <fcntl.h>
00017 #include <unistd.h>
00018 #include <stdlib.h>
00019 #include <stdio.h>
00020 #include <string.h>
00021 #include <errno.h>
00022 
00023 #include <main.h>
00024 #include <globals.h>
00025 #include <handler.h>
00026 #include <ui.h>
00027 #include <simulation.h>
00028 #include <inttypes.h>
00029 #include <strings.h>
00030 #include <mem_compat.h>
00031 #include <stringsearch.h>
00032 
00036 struct embedded_savegame {
00037         GameStruct gs;  
00038         char *world;    
00039 };
00040 
00042 struct save_tag {
00043         int gamecount; 
00044         struct embedded_savegame *games; 
00045 };
00046 typedef struct save_tag savegame_t;
00047 
00048 #define _SAVEGAME_BE_IMPL
00049 #include <savegame_be.h>
00050 
00051 /*
00052 static Int8
00053 read_int8(int fd)
00054 {
00055         Int8 rv;
00056         read(fd, &rv, 1);
00057         return (rv);
00058 }
00059 
00060 static void
00061 write_int8(int fd, Int8 value)
00062 {
00063         write(fd, &value, 1);
00064 }
00065 
00066 static Int16
00067 read_int16(int fd)
00068 {
00069         Int8 by[2];
00070         read(fd, by, 2);
00071         return (by[0] << 8 | by[1]);
00072 }
00073 
00074 static void
00075 write_int16(int fd, Int16 value)
00076 {
00077         write_int8(fd, (value >> 8) & 0xff);
00078         write_int8(fd, value & 0xff);
00079 }
00080 
00081 static Int32
00082 read_int32(int fd)
00083 {
00084         Int8 by[4];
00085         read(fd, by, 4);
00086         return (by[0] << 24 | by[1] << 16 | by[2] << 8 | by[3]);
00087 }
00088 
00089 static void
00090 write_int32(int fd, Int32 value)
00091 {
00092         write_int16(fd, (value >> 16) & 0xffff);
00093         write_int16(fd, value & 0xffff);
00094 }
00095 */
00096 
00097 /*
00098 static char *
00099 mapm_int8(char *mem, char *val)
00100 {
00101         *val = *mem;
00102         return (mem + 1);
00103 }
00104 */
00105 
00106 /*
00107  * \brief map a memory element that's 16 bits long
00108  * \param mem the memory pointer to start at
00109  * \param val the value to fill
00110  * \return pointer to after the read structure
00111  */
00112 static unsigned char *
00113 mapm_int16(unsigned char *mem, unsigned char *val)
00114 {
00115         *(Int16 *)val = (mem[0] << 8 | mem[1]);
00116         return (mem + 2);
00117 }
00118 
00125 static unsigned char *
00126 mapm_int32(unsigned char *mem, unsigned char *val)
00127 {
00128         *(Int32 *)val = (mem[0] << 24 | mem[1] << 16 | mem[2] << 8 | mem[3]);
00129         return (mem + 4);
00130 }
00131 
00132 /*
00133  * \brief read the palm game structure and the map.
00134  * \param mem the pointer to the start of the memory of the game
00135  * \param new the pointer to the gamestructure to fill with the data
00136  * \param map pointer to the pointer that will be filled with the map
00137  * \return the pointer to just after the structure.
00138  *
00139  * This routine reads in the palm structure and it's corresponding map from
00140  * a mem-mapped copy of the file. If you change the savegame structure you
00141  * need to make sure that the reading routines here match the declarations
00142  * in the GameStruct structure, otherwise you read in garbage.
00143  */
00144 static char *
00145 read_palmstructure(char *mem, GameStruct *new, char **map)
00146 {
00147         int i;
00148         int j;
00149         char *ptr = (char *)new;
00150         size_t map_size;
00151 
00152         printf("starting from: %p\n", mem);
00153         bzero(new, sizeof (*new));
00154 
00155         /* savegame identifier */
00156         for (i = 0; i < 4; i++)
00157                 *(ptr + i) = *mem++;
00158 
00159         new->mapx = *mem++;
00160         new->mapy = *mem++;
00161 
00162         new->map_xpos = *mem++;
00163         new->map_ypos = *mem++;
00164 
00165         mem = mapm_int32(mem, (char *)&new->credits);
00166         mem = mapm_int32(mem, (char *)&new->TimeElapsed);
00167 
00168         new->tax + *mem++;
00169         new->gameLoopSeconds = *mem++;
00170         new->diff_disaster = *mem++;
00171         new->gas_bits = *mem++;
00172         bcopy(mem, new->cityname, CITYNAMELEN);
00173         mem += CITYNAMELEN;
00174         for (i = 0; i < ue_tail; i++)
00175                 new->upkeep[i] = *mem++;
00176         new->gridsToUpdate = *mem++;
00177 
00178         mem = mapm_int16(mem, (char *)&new->evaluation);
00179         i = 0;
00180         while (i < st_tail) {
00181                 for (j = 0; j < STATS_COUNT; j++) {
00182                         mem = mapm_int16(mem,
00183                             (char *)&new->statistics[i].last_ten[j]);
00184                 }
00185                 for (j = 0; j < STATS_COUNT; j++) {
00186                         mem = mapm_int16(mem,
00187                             (char *)&new->statistics[i].last_century[j]);
00188                 }
00189                 i++;
00190         }
00191         i = 0;
00192         while (i < NUM_OF_UNITS) {
00193                 mem = mapm_int16(mem, (char *)&new->units[i].x);
00194                 mem = mapm_int16(mem, (char *)&new->units[i].y);
00195                 mem = mapm_int16(mem, (char *)&new->units[i].active);
00196                 new->units[i].type = *mem++;
00197                 mem += 1;
00198                 i++;
00199         }
00200         i = 0;
00201         while (i < NUM_OF_OBJECTS) {
00202                 mem = mapm_int16(mem, (char *)&new->objects[i].x);
00203                 mem = mapm_int16(mem, (char *)&new->objects[i].y);
00204                 mem = mapm_int16(mem, (char *)&new->objects[i].dir);
00205                 mem = mapm_int16(mem, (char *)&new->objects[i].active);
00206                 i++;
00207         }
00208         map_size = (sizeof (welem_t) + sizeof (selem_t)) *
00209             new->mapx * new->mapy;
00210         ptr = malloc(map_size);
00211         *map = ptr;
00212         printf("map starting from: %p for %d\n", mem, map_size);
00213         for (i = 0; i < new->mapx * new->mapy; ptr+=2, i++) {
00214                 mem = mapm_int16(mem, ptr);
00215         }
00216         return (mem);
00217 }
00218 
00219 /*
00220 static void
00221 write_palmstructure(GameStruct *new, int fd)
00222 {
00223         int i;
00224         int j;
00225 
00226         write(fd, new->gsi.version, 4);
00227         write_int8(fd, new->gsi.mapx);
00228         write_int8(fd, new->gsi.mapy);
00229         write_int16(fd, new->gsi.map_xpos);
00230         write_int16(fd, new->gsi.map_ypos);
00231         write_int32(fd, new->gsi.credits);
00232         write_int32(fd, new->gsi.TimeElapsed);
00233         write_int8(fd, new->gsi.tax);
00234         write_int8(fd, new->gsi.gameLoopSeconds);
00235         write_int8(fd, new->gsi.diff_disaster);
00236         write_int8(fd, new->gsi.auto_bulldoze);
00237         write(fd, new->gsi.cityname, CITYNAMELEN);
00238         write_int8(fd, new->gsi.upkeep[0]);
00239         write_int8(fd, new->gsi.upkeep[1]);
00240         write_int8(fd, new->gsi.upkeep[2]);
00241         write_int16(fd, new->gsi.evaluation);
00242         write_int8(fd, new->gsi.c_units);
00243         write_int8(fd, new->gsi.c_objects);
00244         i = 0;
00245         while (i < si_tail) {
00246                 for (j = 0; j < STATS_COUNT; j++) {
00247                         write_int16(fd, new->gsi.statistics[i].last_ten[j]);
00248                 }
00249                 for (j = 0; j < STATS_COUNT; j++) {
00250                         write_int16(fd, new->gsi.statistics[i].last_century[j]);
00251                 }
00252                 i++;
00253         }
00254         i = 0;
00255         while (i < new->gsi.c_units) {
00256                  write_int16(fd, new->units[i].x);
00257                  write_int16(fd, new->units[i].y);
00258                  write_int16(fd, new->units[i].active);
00259                  write_int16(fd, new->units[i].type);
00260                 i++;
00261         }
00262         i = 0;
00263         while (i < new->gsi.c_objects) {
00264                  write_int16(fd, new->objects[i].x);
00265                  write_int16(fd, new->objects[i].y);
00266                  write_int16(fd, new->objects[i].dir);
00267                  write_int16(fd, new->objects[i].active);
00268                 i++;
00269         }
00270 }
00271 */
00272 
00273 savegame_t *
00274 savegame_open(char *filename)
00275 {
00276         struct stat st;
00277         savegame_t *rv = (savegame_t *)calloc(1, sizeof (savegame_t));
00278         int fd = open(filename, O_RDONLY, 0666);
00279         char *buf, *buf2, *buf3;
00280         size_t size;
00281         char sbuf[4];
00282 
00283         if (rv == NULL) {
00284                 perror("calloc");
00285                 return (NULL);
00286         }
00287 
00288         if (fd == -1) {
00289                 perror("open");
00290                 return (NULL);
00291         }
00292 
00293         read(fd, sbuf, 4);
00294         if (0 == memcmp(sbuf, SAVEGAMEVERSION, 4)) {
00295                 size_t worldsize;
00296                 lseek(fd, SEEK_SET, 0);
00297                 rv->gamecount = 1;
00298                 rv->games = calloc(1, sizeof (struct embedded_savegame));
00299                 read(fd, &rv->games[0].gs, sizeof (GameStruct));
00300                 worldsize = (rv->games[0].gs.mapx * rv->games[0].gs.mapy) *
00301                     (sizeof (selem_t) + sizeof (welem_t));
00302                 rv->games[0].world = calloc(1, worldsize);
00303                 read(fd, (void *)worldPtr, worldsize);
00304                 close(fd);
00305                 return(rv);
00306         }
00307 
00308         /* It's a palmos savegame structure */
00309 
00310         if (-1 == fstat(fd, &st)) {
00311                 perror("fstat");
00312                 close(fd);
00313                 return (NULL);
00314         }
00315         size = st.st_size;
00316 
00317         buf = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
00318         if (buf == MAP_FAILED) {
00319                 perror("mmap");
00320                 close(fd);
00321                 return (NULL);
00322         }
00323         close(fd);
00324         buf2 = inMem(buf, size, SAVEGAMEVERSION, 4);
00325         while (buf2 != NULL) {
00326                 rv->gamecount++;
00327                 rv->games = realloc(rv->games,
00328                     rv->gamecount * sizeof (struct embedded_savegame));
00329                 buf3 = buf2;
00330                 buf2 = read_palmstructure(buf2,
00331                     &rv->games[rv->gamecount - 1].gs,
00332                     &rv->games[rv->gamecount - 1].world);
00333                 size -= (buf2 - buf3);
00334                 buf2 = inMem(buf2, size, SAVEGAMEVERSION, 4);
00335         }
00336         munmap(buf, st.st_size);
00337         return (rv);
00338 }
00339 
00340 void
00341 savegame_close(savegame_t *sg)
00342 {
00343         int index;
00344 
00345         for (index = 0; index < sg->gamecount; index++) {
00346                 free(sg->games[index].world);
00347         }
00348         free(sg->games);
00349         free(sg);
00350 }
00351 
00352 char *
00353 savegame_getcityname(savegame_t *sg, int item)
00354 {
00355         if (sg == NULL || item >= sg->gamecount)
00356                 return (NULL);
00357         else
00358                 return (sg->games[item].gs.cityname);
00359 }
00360 
00361 int
00362 savegame_getcity(savegame_t *sg, int item, GameStruct *gs, char **map)
00363 {
00364         size_t newl = 0;
00365         if (sg == NULL || item >= sg->gamecount)
00366                 return (-1);
00367         bcopy(&sg->games[item].gs, gs, sizeof (GameStruct));
00368         newl = (sizeof (welem_t) + sizeof (selem_t)) * gs->mapx * gs->mapy;
00369         *map = (char *)realloc (*map, newl);
00370         bcopy(sg->games[item].world, *map, newl);
00371         return (0);
00372 }
00373 
00374 int
00375 savegame_setcity(savegame_t *sg, int item, GameStruct *gs, char *map)
00376 {
00377         size_t newl;
00378 
00379         if (map == NULL || sg == NULL || item >= sg->gamecount)
00380                 return (-1);
00381         bcopy(gs, &sg->games[item].gs, sizeof (GameStruct));
00382         newl = sizeof (selem_t) + sizeof (welem_t) * gs->mapx * gs->mapy;
00383         sg->games[item].world = realloc(sg->games[item].world, newl);
00384         bcopy(map, sg->games[item].world, newl);
00385         return (0);
00386 }
00387 
00388 int
00389 savegame_citycount(savegame_t *sg)
00390 {
00391         if (sg == NULL) return (-1);
00392         return (sg->gamecount);
00393 }
00394 
00395 int
00396 load_defaultfilename(void)
00397 {
00398         savegame_t *sg = savegame_open(getCityFileName());
00399         if (sg == NULL)
00400                 return (-1);
00401         if (worldPtr != NULL) free(worldPtr);
00402         savegame_getcity(sg, 0, &game, (char **)&worldPtr);
00403         savegame_close(sg);
00404         return (0);
00405 }
00406 
00407 int
00408 save_defaultfilename()
00409 {
00410         return(save_filename(getCityFileName(), &game, worldPtr));
00411 }
00412 
00413 int
00414 save_filename(char *sel, GameStruct *gs, char *world)
00415 {
00416         int fd, ret;
00417         ssize_t worldsize = gs->mapx * gs->mapy *
00418             (sizeof (selem_t) + sizeof (welem_t));
00419 
00420         if (sel == NULL) {
00421                 return (-1);
00422         }
00423         WriteLog("Saving game as %s...\n", sel);
00424 
00425         fd = open(sel,
00426             O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
00427         if (fd == -1) {
00428                 perror("open"); /* TODO: make this nicer */
00429                 return (-1);
00430         }
00431         /* God, I love to write all my vars at one time */
00432         /* using a struct :D */
00433 
00434         ret = write(fd, (void*)gs, sizeof (GameStruct));
00435         if (ret == -1) {
00436                 perror("write game"); /* TODO: make this nicer */
00437                 return (-1);
00438         } else if (ret != sizeof (GameStruct)) {
00439                 WriteLog("Whoops, couldn't write full length of game\n");
00440                 return (-1);
00441         }
00442 
00443         /* and now the great worldPtr :D */
00444         ret = write(fd, (void*)world, (size_t)worldsize);
00445         if (ret == -1) {
00446                 perror("write world"); /* TODO: make this nicer */
00447                 return (-1);
00448         } else if (ret != worldsize) {
00449                 WriteLog("Whoops, couldn't write full length of world\n");
00450                 return (-1);
00451         }
00452 
00453         if (close(fd) == -1) {
00454                 perror("close"); /* TODO: make this nicer */
00455                 return (-1);
00456         }
00457         return (0);
00458 }
00459 
00460 void
00461 NewGame(void)
00462 {
00463         InitGameStruct();
00464         setDifficultyLevel(0);
00465         setDisasterLevel(getDifficultyLevel() + 1);
00466         setMapSize(100, 100);
00467         ConfigureNewGame();
00468 }
00469 
00470 static char *cityfile;
00471 
00472 char *
00473 getCityFileName(void)
00474 {
00475         return (cityfile);
00476 }
00477 
00478 int
00479 setCityFileName(char *newName)
00480 {
00481         if (strcasecmp(newName + strlen(newName) - 4, ".pdb") == 0)
00482                 return (-1);
00483         if (cityfile != NULL)
00484                 free(cityfile);
00485         cityfile = strdup(newName);
00486         return (0);
00487 }

Generated on Mon Aug 30 19:44:15 2004 for pocketcity by doxygen1.2.18