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
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
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
00134
00135
00136
00137
00138
00139
00140
00141
00142
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
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
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
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
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");
00429 return (-1);
00430 }
00431
00432
00433
00434 ret = write(fd, (void*)gs, sizeof (GameStruct));
00435 if (ret == -1) {
00436 perror("write game");
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
00444 ret = write(fd, (void*)world, (size_t)worldsize);
00445 if (ret == -1) {
00446 perror("write world");
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");
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 }