Main Page   Data Structures   File List   Data Fields   Globals   Related Pages  

palm/savegame_be.c

Go to the documentation of this file.
00001 
00005 #include <PalmOS.h>
00006 #include <StringMgr.h>
00007 #include <Form.h>
00008 
00009 #include <stddef.h>
00010 #include <zakdef.h>
00011 #include <simcity.h>
00012 #include <globals.h>
00013 #include <handler.h>
00014 #include <locking.h>
00015 #include <logging.h>
00016 #include <palmutils.h>
00017 #include <simcity_resconsts.h>
00018 #include <resCompat.h>
00019 #include <savegame_be.h>
00020 #include <mem_compat.h>
00021 #include <pack.h>
00022 #include <beam.h>
00023 
00024 #define MAXSAVEGAMECOUNT        50
00025 #define DEAD    "PCNO"
00026 
00027 static int ReadCityRecord(MemHandle rec, GameStruct *gs,
00028     MemPtr *wp, MemPtr *fp) SAVE_SECTION;
00029 static void WriteCityRecord(MemHandle rec, GameStruct *gs,
00030     MemPtr wp, MemPtr fp) SAVE_SECTION;
00031 static int SaveGameByIndex(UInt16 index) SAVE_SECTION;
00032 static int LoadGameByIndex(UInt16 index) SAVE_SECTION;
00033 static void getAutoSaveName(char *name) SAVE_SECTION;
00034 static void DeleteGameByIndex(UInt16 index) SAVE_SECTION;
00035 static Int16 comparator(void *p1, void *p2, Int32 other) SAVE_SECTION;
00036 
00037 static DmOpenRef sgref = 0;
00038 
00039 DmOpenRef
00040 OpenMyDB(void)
00041 {
00042         Err err = 0;
00043         
00044         if (sgref != NULL)
00045                 return (sgref);
00046         sgref = DmOpenDatabaseByTypeCreator(SGTYP, GetCreatorID(),
00047             dmModeReadWrite);
00048         if (!sgref) {
00049                 err = DmCreateDatabase(0, SGNAME, GetCreatorID(), SGTYP, false);
00050                 if (err)
00051                         return (NULL); /* couldn't create */
00052                 sgref = DmOpenDatabaseByTypeCreator(SGTYP, GetCreatorID(),
00053                     dmModeReadWrite);
00054         }
00055         if (!sgref) {
00056                 /* Could not open savegame database */
00057         }
00058         if (DmNumRecords(sgref) == 0) {
00059                 /*
00060                  * create a record in slot 0 if it's not there.
00061                  * This is used for autosaves. It takes the name
00062                  * of the city
00063                  */
00064                 UInt16 index = dmMaxRecordIndex;
00065                 Char name[CITYNAMELEN];
00066                 MemHandle rec = DmNewRecord(sgref, &index, CITYNAMELEN);
00067                 MemSet(name, CITYNAMELEN, 0);
00068                 if (rec) {
00069                         MemPtr mp = MemHandleLock(rec);
00070                         DmWrite(mp, 0, name, CITYNAMELEN);
00071                         MemHandleUnlock(rec);
00072                         DmReleaseRecord(sgref, index, true);
00073                 }
00074         }
00075         return (sgref);
00076 }
00077 
00078 void
00079 CloseMyDB(void)
00080 {
00081         if (sgref) {
00082                 DmCloseDatabase(sgref);
00083                 sgref = 0;
00084         }
00085 }
00086 
00087 UInt16
00088 FindGameByName(char *name)
00089 {
00090         DmOpenRef db = NULL;
00091         MemHandle rec;
00092         GameStruct *pRec;
00093         UInt16 nRec;
00094         UInt16 gameindex = LASTGAME;
00095 
00096         db = OpenMyDB();
00097         if (db == NULL) {
00098                 FrmCustomAlert(alertID_majorbad,
00099                     "Can't Open/Create the savegame database", NULL, NULL);
00100                 return (gameindex);
00101         }
00102         nRec = DmNumRecords(db);
00103         for (gameindex = 1; gameindex < nRec; gameindex++) {
00104                 rec = DmQueryRecord(db, gameindex);
00105                 if (rec == NULL)
00106                         continue;
00107                 pRec = (GameStruct *)MemHandleLock(rec);
00108                 if (StrCaselessCompare((const Char *)pRec->cityname,
00109                     name) == 0) {
00110                         MemHandleUnlock(rec);
00111                         break;
00112                 }
00113                 MemHandleUnlock(rec);
00114         }
00115 
00116         if (gameindex >= nRec)
00117                 return (LASTGAME);
00118         else
00119                 return (gameindex);
00120 }
00121 
00127 void
00128 ResetViewable(void)
00129 {
00130         WriteLog("Reset viewable\n");
00131         setVisibleX((UInt16)(sWidth / gameTileSize()));
00132         setVisibleY((UInt16)((sHeight / gameTileSize()) - 2));
00133 }
00134 
00135 UInt32
00136 saveGameSize(GameStruct *gs)
00137 {
00138 
00139         UInt32 size = (sizeof (GameStruct) +
00140             gs->mapx * gs->mapy +
00141             ((gs->mapx * gs->mapy + ( (8 / 2) - 1)) / ( 8 / 2 )));
00142         return (size);
00143 }
00144 
00153 static int
00154 ReadCityRecord(MemHandle rec, GameStruct *gs, MemPtr *wp, MemPtr *fp)
00155 {
00156         char *ptemp;
00157         int rv = -1;
00158 
00159         ptemp = (char *)MemHandleLock(rec);
00160         if (ptemp == NULL)
00161                 return (-1);
00162         if (MemCmp(DEAD, (char *)ptemp, 4) == 0)
00163                 goto leave_me;
00164         if (MemCmp(SAVEGAMEVERSION, (char *)ptemp, 4) == 0) {
00165                 UInt32 size;
00166                 MemMove((void *)gs, ptemp, sizeof (GameStruct));
00167                 size = gs->mapx * gs->mapy;
00168                 ptemp += sizeof (GameStruct);
00169                 *wp = gRealloc(*wp, size);
00170                 MemMove(*wp, ptemp, (Int32)size);
00171                 *fp = gRealloc(*fp, size);
00172                 ptemp += size;
00173                 UnpackBits(ptemp, *fp, 2, (Int32)size);
00174                 MemMove(*fp, ptemp, (Int32)size);
00175                 rv = 0;
00176         } else {
00177                 FrmAlert(alertID_invalidSaveVersion);
00178                 rv = -1;
00179         }
00180 
00181 leave_me:
00182         MemHandleUnlock(rec);
00183         return (rv);
00184 }
00185 
00193 static void
00194 WriteCityRecord(MemHandle rec, GameStruct *gs, MemPtr wp, MemPtr fp)
00195 {
00196         void *pRec;
00197         void *pRec2;
00198         UInt32 size;
00199 
00200         pRec = MemHandleLock(rec);
00201         /* write the header and some globals */
00202         DmWrite(pRec, 0, gs, sizeof (GameStruct));
00203         DmWrite(pRec, sizeof (GameStruct), (void *)wp,
00204             gs->mapx * gs->mapy);
00205         size = (gs->mapx * gs->mapy + ((8 / 2) - 1)) / (8 / 2);
00206         pRec2 = gMalloc(size);
00207         PackBits(fp, pRec2, 2, gs->mapx * gs->mapy);
00208         DmWrite(pRec, sizeof (GameStruct) + gs->mapx * gs->mapy,
00209             (void *)pRec2, size);
00210         gFree(pRec2);
00211         MemHandleUnlock(rec);
00212 }
00213 
00219 static int
00220 SaveGameByIndex(UInt16 index)
00221 {
00222         DmOpenRef db = NULL;
00223         MemHandle rec;
00224         UInt16 attr = dmHdrAttrBackup;
00225 
00226         if (index == 0)
00227                 return (0);
00228 
00229         db = OpenMyDB();
00230         if (db == NULL)
00231                 return (-1);
00232         if (index <= DmNumRecords(db)) {
00233                 rec = DmResizeRecord(db, index, saveGameSize(&game));
00234                 rec = DmGetRecord(db, index);
00235         } else {
00236                 index = DmNumRecords(db) + 1;
00237                 rec = DmNewRecord(db, &index, saveGameSize(&game));
00238         }
00239         if (rec) {
00240                 LockZone(lz_world);
00241                 LockZone(lz_flags);
00242                 WriteCityRecord(rec, &game, worldPtr, flagPtr);
00243                 UnlockZone(lz_flags);
00244                 UnlockZone(lz_world);
00245                 DmReleaseRecord(db, index, true);
00246         }
00247 
00248         /* tag DB so it gets saved */
00249         DmSetDatabaseInfo(0, DmFindDatabase(0, SGNAME), NULL, &attr, NULL,
00250             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
00251 
00252         return ((int)index);
00253 }
00254 
00255 int
00256 GameExists(char *name)
00257 {
00258         return (FindGameByName(name) != LASTGAME);
00259 }
00260 
00261 void
00262 SaveGameByName(char *name)
00263 {
00264         UInt16 index;
00265         index = FindGameByName(name);
00266 
00267         SaveGameByIndex(index);
00268 }
00269 
00270 /*
00271 void
00272 CreateNewSaveGame(void)
00273 {
00274         DmOpenRef db;
00275         MemHandle rec;
00276 
00277         UInt16 index = dmMaxRecordIndex;
00278 
00279         db = OpenMyDB();
00280 
00281         / * no, this should NOT be an "else if" * /
00282         if (db == NULL)
00283                 return;
00284         if (DmNumRecords(db) >= MAXSAVEGAMECOUNT) {
00285                 / * TODO: alert user - max is 50 savegames * /
00286         } else {
00287                 index = dmMaxRecordIndex;
00288                 WriteLog("Newbie\n");
00289                 rec = DmNewRecord(db, &index, saveGameSize(&game));
00290                 if (rec) {
00291                         ResetViewable();
00292                         ResumeGame();
00293                         LockZone(lz_world);
00294                         LockZone(lz_flags);
00295                         WriteCityRecord(rec, &game, worldPtr, flagPtr);
00296                         UnlockZone(lz_flags);
00297                         UnlockZone(lz_world);
00298                         DmReleaseRecord(db, index, true);
00299                 }
00300         }
00301 }*/
00302 
00308 static int
00309 LoadGameByIndex(UInt16 index)
00310 {
00311         DmOpenRef db;
00312         MemHandle rec;
00313         short int loaded = -1;
00314 
00315         db = OpenMyDB();
00316 
00317         if (!db)
00318                 return (-1); /* no database */
00319 
00320         if (index == LASTGAME)
00321                 index = DmNumRecords(db) - 1;
00322         rec = DmQueryRecord(db, index);
00323         if (rec) {
00324                 LockZone(lz_world);
00325                 LockZone(lz_flags);
00326                 loaded = ReadCityRecord(rec, &game, &worldPtr, &flagPtr);
00327                 UnlockZone(lz_flags);
00328                 UnlockZone(lz_world);
00329         }
00330         if (loaded != -1) {
00331                 PostLoadGame();
00332                 game.units[NUM_OF_UNITS - 1].type = 0xbb;
00333                 game.objects[0].x = 0x2222;
00334                 game.objects[NUM_OF_OBJECTS - 1].dir = 0x3333;
00335                 ResetViewable();
00336         }
00337 
00338         return (loaded);
00339 }
00340 
00341 
00342 int
00343 LoadGameByName(char *name)
00344 {
00345         UInt16 gameindex = FindGameByName(name);
00346 
00347         if (gameindex != LASTGAME)
00348                 return (LoadGameByIndex(gameindex));
00349         else
00350                 return (-1);
00351 }
00352 
00353 Int32
00354 BeamCityByName(Char *cityName)
00355 {
00356         UInt16 gameindex = FindGameByName(cityName);
00357         MemHandle rec = NULL;
00358         MemPtr rp = NULL;
00359         DmOpenRef db = 0;
00360         Int32 rv = -1;
00361 
00362         if (gameindex == LASTGAME)
00363                 return (rv);
00364 
00365         db = OpenMyDB();
00366         if (!db)
00367                 goto exit_me;
00368         rec = DmQueryRecord(db, gameindex);
00369         if (rec == NULL)
00370                 goto exit_me;
00371         rp = MemHandleLock(rec);
00372         if (rp == NULL)
00373                 goto exit_me;
00374         rv = BeamSend((UInt8 *)rp);
00375 exit_me:
00376         if (rp)
00377                 MemHandleUnlock(rec);
00378         return (rv);
00379 }
00380 
00385 static void
00386 getAutoSaveName(char *name)
00387 {
00388         DmOpenRef db = OpenMyDB();
00389         MemHandle rec;
00390         MemPtr ptr;
00391 
00392         *name = '\0';
00393         if (db == NULL)
00394                 return;
00395 
00396         rec = DmQueryRecord(db, 0);
00397         if (rec) {
00398                 ptr = MemHandleLock(rec);
00399                 MemMove(name, ptr, CITYNAMELEN);
00400                 MemHandleUnlock(rec);
00401         }
00402 }
00403 
00404 int
00405 LoadAutoSave(void)
00406 {
00407         char cityname[CITYNAMELEN];
00408 
00409         getAutoSaveName(cityname);
00410 
00411         if (*cityname != '\0') {
00412                 /* Old format ... autosave == slot0 */
00413                 if (StrNCompare(cityname, SAVEGAMEVERSION, 4) == 0)
00414                         return (LoadGameByIndex(0));
00415         } else {
00416                 return (-1);
00417         }
00418 
00419         return (LoadGameByName(cityname));
00420 }
00421 
00422 void
00423 SetAutoSave(char *name)
00424 {
00425         DmOpenRef db = OpenMyDB();
00426         MemHandle mh;
00427         MemPtr mp;
00428 
00429         if (db == NULL)
00430                 return;
00431 
00432         if (DmNumRecords(db) < 1)
00433                 return;
00434 
00435         mh = DmGetRecord(db, 0);
00436         if (mh == NULL) {
00437                 return;
00438         } else {
00439                 mh = DmResizeRecord(db, 0, CITYNAMELEN);
00440         }
00441 
00442         mp = MemHandleLock(mh);
00443 
00444         if (mp == NULL)
00445                 goto release;
00446 
00447         DmWrite(mp, 0, name, CITYNAMELEN);
00448 
00449         MemHandleUnlock(mh);
00450 
00451 release:
00452         DmReleaseRecord(db, 0, true);
00453 }
00454 
00455 void
00456 DeleteAutoSave(void)
00457 {
00458         char buffer[CITYNAMELEN];
00459 
00460         *buffer = '\0';
00461         SetAutoSave(buffer);
00462 }
00463 
00471 static void
00472 DeleteGameByIndex(UInt16 index)
00473 {
00474         DmOpenRef db;
00475 
00476         db = OpenMyDB();
00477         if (db == NULL) {
00478                 return;
00479         }
00480 
00481         if (DmNumRecords(db) < index)
00482                 return;
00483 
00484         if (index > 0)
00485                 DmRemoveRecord(db, index);
00486 }
00487 
00488 void
00489 DeleteGameByName(char *name)
00490 {
00491         UInt16 gameindex = FindGameByName(name);
00492 
00493         if (gameindex != LASTGAME)
00494                 DeleteGameByIndex(gameindex);
00495 }
00496 
00497 int
00498 RenameCity(char *oldname, char *newname)
00499 {
00500         DmOpenRef db;
00501         MemHandle rec;
00502         GameStruct *pRec;
00503         UInt16 gameindex;
00504         UInt16 nRec;
00505         Boolean dirty = false;
00506 
00507         db = OpenMyDB();
00508 
00509         if (db == NULL)
00510                 return (-1); /* no database */
00511         nRec = DmNumRecords(db);
00512         for (gameindex = 0; gameindex < nRec; gameindex++) {
00513                 rec = DmGetRecord(db, gameindex);
00514                 if (rec == NULL)
00515                         continue;
00516                 pRec = MemHandleLock(rec);
00517                 if (StrCompare((const Char *)pRec->cityname, oldname) == 0) {
00518                         DmStrCopy(pRec, offsetof(GameStruct, cityname),
00519                             newname);
00520                         dirty = true;
00521                 }
00522                 DmReleaseRecord(db, gameindex, dirty);
00523                 if (dirty)
00524                         break;
00525         }
00526         return (dirty);
00527 }
00528 
00529 int
00530 CopyCity(Char *name)
00531 {
00532         DmOpenRef db;
00533         MemHandle rec;
00534         GameStruct *pRec;
00535         UInt16 gameindex;
00536         UInt16 nRec;
00537         Boolean dirty = false;
00538 
00539         db = OpenMyDB();
00540 
00541         if (db == NULL)
00542                 return (-1); /* no database */
00543         nRec = DmNumRecords(db);
00544         for (gameindex = 0; gameindex < nRec; gameindex++) {
00545                 rec = DmQueryRecord(db, gameindex);
00546                 if (rec == NULL)
00547                         continue;
00548                 pRec = MemHandleLock(rec);
00549                 if (StrCompare((const Char *)pRec->cityname, name) == 0) {
00550                         UInt16 reci;
00551                         UInt32 len;
00552                         MemHandle mhp;
00553                         MemPtr pmhp;
00554                         char newCity[CITYNAMELEN];
00555 
00556                         reci = dmMaxRecordIndex;
00557                         len = MemHandleSize(rec);
00558                         mhp = DmNewRecord(db, &reci, len);
00559                         pmhp = MemHandleLock(mhp);
00560                         *newCity = '\0';
00561                         StrNCat(newCity, (char *)pRec->cityname, CITYNAMELEN);
00562                         StrNCat(newCity, " Copy", CITYNAMELEN);
00563                         DmWrite(pmhp, 0, pRec, len);
00564                         DmStrCopy(pmhp, offsetof(GameStruct, cityname),
00565                             newCity);
00566                         MemHandleUnlock(mhp);
00567                         DmReleaseRecord(db, reci, true);
00568                         dirty = true;
00569                 }
00570                 MemHandleUnlock(rec);
00571                 DmReleaseRecord(db, gameindex, false);
00572                 if (dirty)
00573                         break;
00574         }
00575         return (dirty);
00576 }
00577 
00585 static Int16
00586 comparator(void *p1, void *p2, Int32 other)
00587 {
00588         return (StrNCaselessCompare(*(char **)p1, *(char **)p2, other));
00589 }
00590 
00591 char **
00592 CityNames(int *count)
00593 {
00594         DmOpenRef db;
00595         UInt16 index = 0;
00596         MemHandle rec;
00597         unsigned char *pTemp;
00598         unsigned short int nRec;
00599         unsigned short int nsIndex = 0;
00600         char **cities;
00601         char *citystring;
00602 
00603         db = OpenMyDB();
00604         if (db == NULL) {
00605                 return (NULL); /* no database */
00606         }
00607         nRec = DmNumRecords(db);
00608 
00609         if (nRec < 2)
00610                 return (NULL);
00611 
00612         cities = (char **)MemPtrNew(nRec * sizeof (*cities));
00613         citystring = (char *)MemPtrNew(nRec * CITYNAMELEN);
00614 
00615         for (index = 1; index < nRec; index++) {
00616                 rec = DmQueryRecord(db, index);
00617                 if (rec) {
00618                         cities[nsIndex] = citystring;
00619                         citystring += CITYNAMELEN;
00620                         pTemp = (unsigned char *)MemHandleLock(rec);
00621                         StrNCopy(cities[nsIndex], (char *)pTemp +
00622                             offsetof(GameStruct, cityname), CITYNAMELEN);
00623                         MemHandleUnlock(rec);
00624                         nsIndex++;
00625                 }
00626         }
00627         cities[nsIndex] = NULL;
00628         *count = (int)nsIndex;
00629         if (nsIndex > 10)
00630                 SysQSort(cities, nsIndex, sizeof (*cities),
00631                     comparator, CITYNAMELEN);
00632         else if (nsIndex >= 2)
00633                 SysInsertionSort(cities, nsIndex, sizeof (*cities),
00634                     comparator, CITYNAMELEN);
00635         return (cities);
00636 }
00637 
00638 void
00639 FreeCityNames(char **names)
00640 {
00641         char **at = names;
00642         char *gnat;
00643 
00644         if (names == NULL)
00645                 return;
00646 
00647         gnat = *at;
00648 
00649         while (*at != NULL) {
00650                 if (gnat > *at)
00651                         gnat = *at;
00652                 at++;
00653         }
00654         MemPtrFree(gnat);
00655         MemPtrFree(names);
00656 }
00657 

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