static void skipList(bfFile bf) { int len,i; unsigned char type; bfread(bf,&type,1); len=readDword(bf); switch (type) { default: break; case 1: //byte bfseek(bf,len,SEEK_CUR); break; case 2: //short bfseek(bf,len*2,SEEK_CUR); break; case 3: //int bfseek(bf,len*4,SEEK_CUR); break; case 4: //long bfseek(bf,len*8,SEEK_CUR); break; case 5: //float bfseek(bf,len*4,SEEK_CUR); break; case 6: //double bfseek(bf,len*8,SEEK_CUR); break; case 7: //byte array for (i=0;i<len;i++) { int slen=readDword(bf); bfseek(bf,slen,SEEK_CUR); } break; case 8: //string for (i=0;i<len;i++) { int slen=readWord(bf); bfseek(bf,slen,SEEK_CUR); } break; case 9: //list for (i=0;i<len;i++) skipList(bf); break; case 10: //compound for (i=0;i<len;i++) skipCompound(bf); break; case 11: //int array for (i=0;i<len;i++) { int slen=readDword(bf); bfseek(bf,slen*4,SEEK_CUR); } break; } }
void nbtGetFileVersion(bfFile bf, int *version) { int len; //Data/version bfseek(bf,1,SEEK_CUR); //skip type len=readWord(bf); //name length bfseek(bf,len,SEEK_CUR); //skip name () if (nbtFindElement(bf,"Data")!=10) return; if (nbtFindElement(bf,"version")!=3) return; *version=readDword(bf); }
//void nbtGetRandomSeed(bfFile bf,long long *seed) //{ // int len; // *seed=0; // //Data/RandomSeed // bfseek(bf,1,SEEK_CUR); //skip type // len=readWord(bf); //name length // bfseek(bf,len,SEEK_CUR); //skip name () // if (nbtFindElement(bf,"Data")!=10) return; // if (nbtFindElement(bf,"RandomSeed")!=4) return; // *seed=readLong(bf); //} void nbtGetPlayer(bfFile bf,int *px,int *py,int *pz) { int len; *px=*py=*pz=0; //Data/Player/Pos bfseek(bf,1,SEEK_CUR); //skip type len=readWord(bf); //name length bfseek(bf,len,SEEK_CUR); //skip name () if (nbtFindElement(bf,"Data")!=10) return; if (nbtFindElement(bf,"Player")!=10) return; if (nbtFindElement(bf,"Pos")!=9) return; bfseek(bf,5,SEEK_CUR); //skip subtype and num items *px=(int)readDouble(bf); *py=(int)readDouble(bf); *pz=(int)readDouble(bf); }
void nbtGetSpawn(bfFile bf,int *x,int *y,int *z) { int len; *x=*y=*z=0; //Data/SpawnX bfseek(bf,1,SEEK_CUR); //skip type len=readWord(bf); //name length bfseek(bf,len,SEEK_CUR); //skip name () if (nbtFindElement(bf,"Data")!=10) return; if (nbtFindElement(bf,"SpawnX")!=3) return; *x=readDword(bf); if (nbtFindElement(bf,"SpawnY")!=3) return; *y=readDword(bf); if (nbtFindElement(bf,"SpawnZ")!=3) return; *z=readDword(bf); }
static void skipType(bfFile bf,int type) { int len; switch (type) { default: break; case 1: //byte bfseek(bf,1,SEEK_CUR); break; case 2: //short bfseek(bf,2,SEEK_CUR); break; case 3: //int bfseek(bf,4,SEEK_CUR); break; case 4: //long bfseek(bf,8,SEEK_CUR); break; case 5: //float bfseek(bf,4,SEEK_CUR); break; case 6: //double bfseek(bf,8,SEEK_CUR); break; case 7: //byte array len=readDword(bf); bfseek(bf,len,SEEK_CUR); break; case 8: //string len=readWord(bf); bfseek(bf,len,SEEK_CUR); break; case 9: //list skipList(bf); break; case 10: //compound skipCompound(bf); break; case 11: //int array len=readDword(bf); bfseek(bf,len*4,SEEK_CUR); break; } }
void micro_write_file(BFILE* out, BFILE* in, freed_bstring name) { int written = 0; uint16_t store; size_t pos; // Check to make sure we don't have too many entries. if (micro_table_count >= MICRO_MAX_ENTRIES) { printd(LEVEL_WARNING, "ignoring file %s; maximum limit of %u files hit.\n", name.ref->data, MICRO_MAX_ENTRIES); exit(1); } // Copy data. store = (uint16_t)(bftell(out) / 2); while (!bfeof(in)) { bfputc(bfgetc(in), out); written++; } // Store the position so we can jump back to // this position. pos = bftell(out); // Write the entry. bfseek(out, micro_table_addr + micro_table_count * 2, SEEK_SET); bfiwrite(&store, out); store = written / 2; bfiwrite(&store, out); printd(LEVEL_VERBOSE, "wrote file %s at index %u (0x%04X words).\n", name.ref->data, micro_table_count, written / 2); micro_table_count++; // Seek back again. bfseek(out, pos, SEEK_SET); // Clear memory. bautodestroy(name); }
void micro_write_kernel(BFILE* out, BFILE* in, int count) { int written = 0, i; uint16_t store; size_t pos; // Copy data. while (!bfeof(in)) { bfputc(bfgetc(in), out); written++; } // Go back and write the filesystem // information if permitted. pos = bftell(out); bfseek(out, sizeof(uint16_t) * 2, SEEK_SET); bfiread(&store, out); bfseek(out, sizeof(uint16_t) * 2, SEEK_SET); if (store == 0xDEDE) { store = written / 2; bfiwrite(&store, out); } else printd(LEVEL_VERBOSE, "not writing end-of-kernel to 0x0002 (0x0002 is not 0xDEDE).\n"); bfseek(out, pos, SEEK_SET); printd(LEVEL_VERBOSE, "wrote kernel (0x%04X words).\n", written / 2); // Store the position and count of the micro table. micro_table_addr = pos; micro_table_count = 0; // Write out 20 NULL entries (1 addr and 1 size for each entry). store = 0x0000; for (i = 0; i < MICRO_MAX_ENTRIES * 2; i++) bfiwrite(&store, out); }
static void skipCompound(bfFile bf) { int len; unsigned char type=0; do { bfread(bf,&type,1); if (type) { len=readWord(bf); bfseek(bf,len,SEEK_CUR); //skip name skipType(bf,type); } } while (type); }
int nbtGetBlocks(bfFile bf, unsigned char *buff, unsigned char *data, unsigned char *blockLight, unsigned char *biome) { int len,nsections; int biome_save; //int found; #ifndef C99 char *thisName; #endif //Level/Blocks bfseek(bf,1,SEEK_CUR); //skip type len=readWord(bf); //name length bfseek(bf,len,SEEK_CUR); //skip name () if (nbtFindElement(bf,"Level")!=10) return 0; // For some reason, on most maps the biome info is before the Sections; // on others they're after. So, read biome data, then rewind to find Sections. // Format info at http://wiki.vg/Map_Format, though don't trust order. biome_save = *bf.offset; memset(biome, 0, 16*16); if (nbtFindElement(bf,"Biomes")!=7) return 0; { len=readDword(bf); //array length bfread(bf,biome,len); } bfseek(bf,biome_save,SEEK_SET); //rewind to start of section if (nbtFindElement(bf,"Sections")!= 9) return 0; { unsigned char type=0; bfread(bf,&type,1); if (type != 10) return 0; } memset(buff, 0, 16*16*256); memset(data, 0, 16*16*128); memset(blockLight, 0, 16*16*128); nsections=readDword(bf); while (nsections--) { unsigned char y; int save = *bf.offset; if (nbtFindElement(bf,"Y")!=1) //which section is this? return 0; bfread(bf,&y,1); bfseek(bf,save,SEEK_SET); //rewind to start of section //found=0; for (;;) { int ret=0; unsigned char type=0; bfread(bf,&type,1); if (type==0) break; len=readWord(bf); #ifdef C99 char thisName[len+1]; #else thisName=(char *)malloc(len+1); #endif bfread(bf,thisName,len); thisName[len]=0; if (strcmp(thisName,"BlockLight")==0) { //found++; ret=1; len=readDword(bf); //array length bfread(bf,blockLight+16*16*8*y,len); } if (strcmp(thisName,"Blocks")==0) { //found++; ret=1; len=readDword(bf); //array length bfread(bf,buff+16*16*16*y,len); } else if (strcmp(thisName,"Data")==0) { //found++; ret=1; len=readDword(bf); //array length bfread(bf,data+16*16*8*y,len); } #ifndef C99 free(thisName); #endif if (!ret) skipType(bf,type); } } return 1; }
int nbtGetBlocks(bfFile bf, unsigned char *buff, unsigned char *data, unsigned char *blockLight) { int len,nsections; //int found; #ifndef C99 char *thisName; #endif //Level/Blocks bfseek(bf,1,SEEK_CUR); //skip type len=readWord(bf); //name length bfseek(bf,len,SEEK_CUR); //skip name () if (nbtFindElement(bf,"Level")!=10) return 0; if (nbtFindElement(bf,"Sections")!= 9) return 0; { unsigned char type=0; bfread(bf,&type,1); if (type != 10) return 0; } memset(buff, 0, 16*16*256); memset(data, 0, 16*16*128); memset(blockLight, 0, 16*16*128); nsections=readDword(bf); while (nsections--) { unsigned char y; int save = *bf.offset; if (nbtFindElement(bf,"Y")!=1) //which section is this? return 0; bfread(bf,&y,1); bfseek(bf,save,SEEK_SET); //rewind to start of section //found=0; for (;;) { int ret=0; unsigned char type=0; bfread(bf,&type,1); if (type==0) break; len=readWord(bf); #ifdef C99 char thisName[len+1]; #else thisName=(char *)malloc(len+1); #endif bfread(bf,thisName,len); thisName[len]=0; if (strcmp(thisName,"BlockLight")==0) { //found++; ret=1; len=readDword(bf); //array length bfread(bf,blockLight+16*16*8*y,len); } if (strcmp(thisName,"Blocks")==0) { //found++; ret=1; len=readDword(bf); //array length bfread(bf,buff+16*16*16*y,len); } else if (strcmp(thisName,"Data")==0) { //found++; ret=1; len=readDword(bf); //array length bfread(bf,data+16*16*8*y,len); } #ifndef C99 free(thisName); #endif if (!ret) skipType(bf,type); } } return 1; }