void test2(void) { FILE *in1; bfile *in2; int ch; in1 = fopen("bitfiles.c", "rb"); in2 = bfopen("bitfiles.cc", "rb"); if ((NULL == in1) || (NULL == in2)) { printf("Can't open test files\n"); exit(1); } while (!feof(in1) && !feof(in2->file)) { ch = fgetc(in1); if (ch < ' ') ch = '.'; printf(" '%c' ", ch); for (ch = 0; ch < 8; ch++) printf("%c", "01"[bfread(in2)]); printf(" "); } fclose(in1); bfclose(in2); }
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; } }
// this finds an element in a composite list. // it works progressively, so it only finds elements it hasn't come // across yet. static int nbtFindElement(bfFile bf,char *name) { for( ;; ) { unsigned char type=0; bfread(bf,&type,1); if (type==0) return 0; if (compare(bf,name)) return type; skipType(bf,type); } }
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); }
//static unsigned long long readLong(bfFile bf) //{ // int i; // union { // double f; // unsigned long long l; // } fl; // unsigned char buf[8]; // bfread(bf,buf,8); // fl.l=0; // for (i=0;i<8;i++) // { // fl.l<<=8; // fl.l|=buf[i]; // } // return fl.l; //} static double readDouble(bfFile bf) { int i; union { double f; unsigned long long l; } fl; unsigned char buf[8]; bfread(bf,buf,8); fl.l=0; for (i=0;i<8;i++) { fl.l<<=8; fl.l|=buf[i]; } return fl.f; }
static int compare(bfFile bf,char *name) { int ret=0; int len=readWord(bf); #ifdef C99 char thisName[len+1]; #else char *thisName=(char*)malloc(len+1); #endif bfread(bf,thisName,len); thisName[len]=0; if (strcmp(thisName,name)==0) ret=1; #ifndef C99 free(thisName); #endif return ret; }
void test1(void) { bfile *out; bfile *in; FILE *in1; FILE *in2; in = bfopen("bitfiles.c", "rb"); out = bfopen("bitfiles.cc", "wb"); if ((NULL == in) || (NULL == out)) { printf("Can't open/create test files\n"); exit(1); } while (!feof(in->file)) bfwrite(bfread(in), out); bfclose(in); bfclose(out); in1 = fopen("bitfiles.c", "rb"); in2 = fopen("bitfiles.cc", "rb"); if ((NULL == in1) || (NULL == in2)) { printf("Can't open test files for verifying\n"); exit(1); } while (!feof(in1) && !feof(in2)) { if (fgetc(in1) != fgetc(in2)) { printf("Files not identical, copy failed!\n"); exit(1); } } if (!feof(in1) || !feof(in2)) { printf("Not same size, copy failed!\n"); exit(1); } fclose(in1); fclose(in2); }
err_type File_Header_fread(FILE *f, File_Header *fHead) { err_type result; if ((f == NULL) || (fHead == NULL)) return ERR_PARAM_INVALID; if ((result = bfread(f, &(fHead->headCrc), sizeof(fHead->headCrc))) != ERR_NO) return result; if ((result = bfread(f, &(fHead->fileNameLength), sizeof(fHead->fileNameLength))) != ERR_NO) return result; if ((result = bfread(f, fHead->fileName, fHead->fileNameLength * sizeof(fHead->fileName[0]))) != ERR_NO) return result; if ((result = bfread(f, &(fHead->attr), sizeof(fHead->attr))) != ERR_NO) return result; if ((result = bfread(f, &(fHead->method), sizeof(fHead->method))) != ERR_NO) return result; if ((result = bfread(f, &(fHead->fileSize), sizeof(fHead->fileSize))) != ERR_NO) return result; /*if ((result = bfread(f, &(fHead->fileCrc), sizeof(fHead->fileCrc))) != ERR_NO) return result;*/ return File_Header_checkCrc(fHead); }
static unsigned int readDword(bfFile bf) { unsigned char buf[4]; bfread(bf,buf,4); return (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3]; }
static unsigned short readWord(bfFile bf) { unsigned char buf[2]; bfread(bf,buf,2); return (buf[0]<<8)|buf[1]; }
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; }