//---------------------------------------------- // SECTION 3: BIT MAP SECTION (BMS) //---------------------------------------------- bool GribV1Record::readGribSection3_BMS(ZUFILE* file) { fileOffset3 = zu_tell(file); if (! hasBMS) { sectionSize3 = 0; return ok; } sectionSize3 = readInt3(file); (void) readChar(file); int bitMapFollows = readInt2(file); if (bitMapFollows != 0) { return ok; } BMSbits = new zuchar[sectionSize3-6]; if (!BMSbits) { //erreur("Record: out of memory"); ok = false; } for (zuint i=0; i<sectionSize3-6; i++) { BMSbits[i] = readChar(file); } return ok; }
static bool patchApplyIPS(const char *patchname, u8 **r, int *s) { // from the IPS spec at http://zerosoft.zophar.net/ips.htm FILE *f = fopen(patchname, "rb"); if(!f) return false; bool result = false; u8 *rom = *r; int size = *s; if(fgetc(f) == 'P' && fgetc(f) == 'A' && fgetc(f) == 'T' && fgetc(f) == 'C' && fgetc(f) == 'H') { int b; int offset; int len; result = true; for(;;) { // read offset offset = readInt3(f); // if offset == EOF, end of patch if(offset == 0x454f46 || offset == -1) break; // read length len = readInt2(f); if(!len) { // len == 0, RLE block len = readInt2(f); // byte to fill int c = fgetc(f); if(c == -1) break; b = (u8)c; } else b= -1; // check if we need to reallocate our ROM if((offset + len) >= size) { size *= 2; rom = (u8 *)realloc(rom, size); *r = rom; *s = size; } if(b == -1) { // normal block, just read the data if(fread(&rom[offset], 1, len, f) != (size_t)len) break; } else { // fill the region with the given byte while(len--) { rom[offset++] = b; } } } } // close the file fclose(f); return result; }
//---------------------------------------------- // SECTION 4: BINARY DATA SECTION (BDS) //---------------------------------------------- bool GribV1Record::readGribSection4_BDS(ZUFILE* file) { fileOffset4 = zu_tell(file); sectionSize4 = readInt3(file); // byte 1-2-3 zuchar flags = readChar(file); // byte 4 scaleFactorE = readSignedInt2(file); // byte 5-6 refValue = readFloat4(file); // byte 7-8-9-10 nbBitsInPack = readChar(file); // byte 11 scaleFactorEpow2 = pow(2.0,scaleFactorE); unusedBitsEndBDS = flags & 0x0F; isGridData = (flags&0x80) ==0; isSimplePacking = (flags&0x80) ==0; isFloatValues = (flags&0x80) ==0; //printf("BDS type=%3d - bits=%02d - level %3d - %d\n", dataType, nbBitsInPack, levelType,levelValue); if (! isGridData) { //erreur("Record: need grid data"); ok = false; } if (! isSimplePacking) { //erreur("Record: need simple packing"); ok = false; } if (! isFloatValues) { //erreur("Record: need double values"); ok = false; } if (!ok) { return ok; } // Allocate memory for the data data = new float[Ni*Nj]; if (!data) { //erreur("Record: out of memory"); ok = false; } zuint startbit = 0; int datasize = sectionSize4-11; zuchar *buf = new zuchar[datasize+4]; // +4 pour simplifier les decalages ds readPackedBits if (!buf) { //erreur("Record: out of memory"); ok = false; } if (zu_read(file, buf, datasize) != datasize) { //erreur("Record: data read error"); ok = false; eof = true; } if (!ok) { return ok; } // Initialize the las 4 bytes of buf since we didn't read them buf[datasize+0] = buf[datasize+1] = buf[datasize+2] = buf[datasize+3] = 0; // Read data in the order given by isAdjacentI zuint i, j, x; int ind; if (isAdjacentI) { for (j=0; j<Nj; j++) { for (i=0; i<Ni; i++) { if (!hasDiDj && !isScanJpositive) { ind = (Nj-1 -j)*Ni+i; } else { ind = j*Ni+i; } if (hasValue(i,j)) { x = readPackedBits(buf, startbit, nbBitsInPack); data[ind] = (refValue + x*scaleFactorEpow2)/decimalFactorD; startbit += nbBitsInPack; } else { data[ind] = (float) GRIB_NOTDEF; } } } } else { for (i=0; i<Ni; i++) { for (j=0; j<Nj; j++) { if (!hasDiDj && !isScanJpositive) { ind = (Nj-1 -j)*Ni+i; } else { ind = j*Ni+i; } if (hasValue(i,j)) { x = readPackedBits(buf, startbit, nbBitsInPack); startbit += nbBitsInPack; data[ind] = (refValue + x*scaleFactorEpow2)/decimalFactorD; } else { data[ind] = (float)GRIB_NOTDEF; } } } } if (buf) { delete [] buf; buf = NULL; } return ok; }
//---------------------------------------------- // SECTION 2: THE GRID DESCRIPTION SECTION (GDS) //---------------------------------------------- bool GribV1Record::readGribSection2_GDS(ZUFILE* file) { if (! hasGDS) return 0; fileOffset2 = zu_tell(file); sectionSize2 = readInt3(file); // byte 1-2-3 readChar(file); // byte 4 => NV readChar(file); // byte 5 => PV gridType = readChar(file); // byte 6 if (gridType != 0) { erreur("Record: unknown grid type GDS(6) : %d",gridType); ok = false; } Ni = readInt2(file); // byte 7-8 Nj = readInt2(file); // byte 9-10 La1 = readSignedInt3(file)/1000.0; // byte 11-12-13 Lo1 = readSignedInt3(file)/1000.0; // byte 14-15-16 resolFlags = readChar(file); // byte 17 La2 = readSignedInt3(file)/1000.0; // byte 18-19-20 Lo2 = readSignedInt3(file)/1000.0; // byte 21-22-23 if (Lo1>=0 && Lo1<=180 && Lo2<0) { Lo2 += 360.0; // cross the 180 deg meridien,beetwen alaska and russia } Di = readSignedInt2(file)/1000.0; // byte 24-25 Dj = readSignedInt2(file)/1000.0; // byte 26-27 while ( Lo1> Lo2 && Di >0) { // horizontal size > 360 ° Lo1 -= 360.0; } double val=Lo2+Di; while(val>=360) val-=360; if(val==Lo1) isFull=true; hasDiDj =(resolFlags&0x80) !=0; scanFlags = readChar(file); // byte 28 isScanIpositive = (scanFlags&0x80) ==0; isScanJpositive = (scanFlags&0x40) !=0; isAdjacentI = (scanFlags&0x20) ==0; if (Lo2 > Lo1) { lonMin = Lo1; lonMax = Lo2; } else { lonMin = Lo2; lonMax = Lo1; } if (La2 > La1) { latMin = La1; latMax = La2; } else { latMin = La2; latMax = La1; } if (Ni<=1 || Nj<=1) { erreur("Recordd: Ni=%u Nj=%u",Ni,Nj); ok = false; } else { Di = (Lo2-Lo1) / (Ni-1); Dj = (La2-La1) / (Nj-1); } if (false) { printf("====\n"); printf("Lo1=%f Lo2=%f La1=%f La2=%f\n", Lo1,Lo2,La1,La2); printf("Ni=%u Nj=%u\n", Ni,Nj); printf("hasDiDj=%d Di,Dj=(%f %f)\n", hasDiDj, Di,Dj); printf("hasBMS=%d\n", hasBMS); printf("isScanIpositive=%d isScanJpositive=%d isAdjacentI=%d\n", isScanIpositive,isScanJpositive,isAdjacentI ); } return ok; }
//============================================================== // Lecture des donnees //============================================================== //---------------------------------------------- // SECTION 0: THE INDICATOR SECTION (IS) //---------------------------------------------- bool GribV1Record::readGribSection0_IS(ZUFILE* file) { char strgrib[4]; memset (strgrib, 0, sizeof (strgrib)); zuint initFoffset; fileOffset0 = zu_tell(file); initFoffset=fileOffset0; #if 1 char buf[1]; memset (buf, 0, sizeof (buf)); while(true) { if(zu_read(file,buf,1)!=1) break; ++fileOffset0; if(buf[0]!='G') continue; if(zu_read(file,buf,1)!=1) break; ++fileOffset0; if(buf[0]!='R') { if(buf[0]=='G') zu_seek(file,--fileOffset0,SEEK_SET); continue; } if(zu_read(file,buf,1)!=1) break; ++fileOffset0; if(buf[0]!='I') { if(buf[0]=='G') zu_seek(file,--fileOffset0,SEEK_SET); continue; } if(zu_read(file,buf,1)!=1) break; ++fileOffset0; if(buf[0]!='B') { if(buf[0]=='G') zu_seek(file,--fileOffset0,SEEK_SET); continue; } strgrib[0]='G'; strgrib[1]='R'; strgrib[2]='I'; strgrib[3]='B'; break; } #else while((zu_read(file, strgrib, 4) == 4) && (strgrib[0] != 'G' || strgrib[1] != 'R' || strgrib[2] != 'I' || strgrib[3] != 'B')) { zu_seek(file,++fileOffset0,SEEK_SET); } #endif if(strgrib[0] != 'G' || strgrib[1] != 'R' || strgrib[2] != 'I' || strgrib[3] != 'B') { if((fileOffset0-10)>initFoffset) // displaying error msg only if we are really far from initial offset qWarning() << "Can't find next record / EOF - offset=" << fileOffset0 << ", initOffset=" << initFoffset ; ok = false; eof = true; return false; } seekStart=zu_tell(file)-4; totalSize = readInt3(file); //qWarning() << "Start = " << seekStart << ", size = " << totalSize; editionNumber = readChar(file); if (editionNumber != 1) { ok = false; eof = true; return false; } return true; }