Map loading

The map loading has a delayed section loading mechanism, so that the start time of large maps is minimized (of course this only helps if the map is divided into sections). On map loading time only the [[Map]] and [[Section]] structures are loaded and the object records are skipped. «*»= Map * LoadMap(char *name) DmOpenRef NewMap; Map *newm; LocalID id; VoidHand RecHandle; Ptr RecPointer; int i,recnum; Section *sec;

if(DmFindDatabase(0,name) == 0) return(NULL);

id=DmFindDatabase(0,name); NewMap=DmOpenDatabase(0,id,dmModeReadWrite);

RecHandle=DmGetRecord(NewMap,0); RecPointer=MemHandleLock(RecHandle);

newm=MemPtrNew(sizeof(Map)); MemMove(newm,RecPointer,sizeof(Map)); newm->Name=MemPtrNew(StrLen((char*)RecPointer+sizeof(Map))+1); StrCopy(newm->Name,(char*)RecPointer+sizeof(Map));

newm->sections=MemPtrNew(newm->sectionNum*sizeof(Section));

MemHandleUnlock(RecHandle); DmReleaseRecord(NewMap,0,false);

recnum=1; for(i=0;i<newm->sectionNum;i++) sec=&newm->sections[i]; sec->loaded=false; sec->Name=NULL; sec->items=NULL; sec->itemNum=0;

RecHandle=DmGetRecord(NewMap,recnum); RecPointer=MemHandleLock(RecHandle);

sec->itemNum=*(UInt *)RecPointer; sec->Name=MemPtrNew(StrLen((char*)RecPointer+sizeof(UInt))+1); StrCopy(sec->Name,(char*)RecPointer+sizeof(UInt)); MemHandleUnlock(RecHandle); DmReleaseRecord(NewMap,recnum,false); recnum+=sec->itemNum+1;

DmCloseDatabase(NewMap);

currentMap=newm; section=0; return(newm); @

Load the objects starting at [[index]] into section [[sec]]. Note that this is a pretty low level function, since all the index calculation has already happened. You probably want to use the [[ensureSectionLoaded]] function to load sections. «*»= void LoadSection(DmOpenRef map,Section *sec,UInt index) int i; VoidHand RecHandle; Ptr RecPointer;

if(sec->Name) MemPtrFree(sec->Name); if(sec->items) MemPtrFree(sec->items);

RecHandle=DmGetRecord(map,index); RecPointer=MemHandleLock(RecHandle);

sec->itemNum=*(UInt *)RecPointer; sec->Name=MemPtrNew(StrLen((char*)RecPointer+sizeof(UInt))+1); sec->items=MemPtrNew(sec->itemNum*sizeof(Item)); StrCopy(sec->Name,(char*)RecPointer+sizeof(UInt)); MemMove(&sec->si, RecPointer+sizeof(UInt)+StrLen(sec->Name)+1, sizeof(ScreenInfo)); MemHandleUnlock(RecHandle); DmReleaseRecord(map,index++,false);

for(i=0;i<sec->itemNum;i++) RecHandle=DmGetRecord(map,index); RecPointer=MemHandleLock(RecHandle);

«Initialize and read next object» index++;

sec->loaded=true; @

The initialisation is done in 3 steps:

  1. Copy the type to the new object
  2. One the type is known, the object can be properly initialized
  3. Copy the rest of the object data from the record
«Initialize and read next object»= MemMove(&sec->items[i].type, RecPointer,sizeof(Byte));

MemHandleUnlock(RecHandle); DmReleaseRecord(map,index,false);

switch(sec->items[i].type) case LOCATION: InitLocation(&sec->items[i]); break; case CONNECTION: InitConnection(&sec->items[i]); break; case TEXT: InitText(&sec->items[i]); break;

ReadItem(&sec->items[i],map,index); @

«*»= static void ensureAllSectionsLoaded(Map *map) int i; int recnum=1; UInt recs; Section *sec; char vbuf[40]; LocalID id; DmOpenRef mapDB;

StrPrintF(vbuf,"

if((id=DmFindDatabase(0,vbuf)) == 0) return; mapDB=DmOpenDatabase(0,id,dmModeReadWrite); recs=DmNumRecords(mapDB);

for(i=0;i<map->sectionNum;i++) sec=&map->sections[i]; if(!sec->loaded) LoadSection(mapDB,sec,recnum); recnum+=sec->itemNum+1; else UInt litems; VoidHand RecHandle; Ptr RecPointer;

// section is new if(recnum>=recs) return;

RecHandle=DmGetRecord(mapDB,recnum); RecPointer=MemHandleLock(RecHandle);

litems=*(UInt *)RecPointer; MemHandleUnlock(RecHandle); DmReleaseRecord(mapDB,recnum,false); recnum+=litems+1; DmCloseDatabase(mapDB); @

«*»= void ensureSectionLoaded(Map *map, UInt secnum) int i; int recnum=1; UInt recs; Section *sec; char vbuf[40]; LocalID id; DmOpenRef mapDB;

if(map->sections[secnum].loaded) return;

StrPrintF(vbuf,"

id=DmFindDatabase(0,vbuf); mapDB=DmOpenDatabase(0,id,dmModeReadWrite); recs=DmNumRecords(mapDB);

for(i=0;i<secnum;i++) sec=&map->sections[i]; if(!sec->loaded) recnum+=sec->itemNum+1; else UInt litems; VoidHand RecHandle; Ptr RecPointer;

// section is new if(recnum>=recs) return;

RecHandle=DmGetRecord(mapDB,recnum); RecPointer=MemHandleLock(RecHandle);

litems=*(UInt *)RecPointer; MemHandleUnlock(RecHandle); DmReleaseRecord(mapDB,recnum,false); recnum+=litems+1;

sec=&map->sections[secnum]; LoadSection(mapDB,sec,recnum);

DmCloseDatabase(mapDB); @