GraphicComp* ImportCmd::PPM_Image (const char* filename) { GraphicComp* comp = nil; FILE* file = fopen(filename, "r"); boolean compressed; file = CheckCompression(file, filename, compressed); if (file != nil) { char line[1000]; do { fgets(line, 1000, file); } while (strcmp(line, "gsave\n") != 0); fgets(line, 1000, file); // translate fgets(line, 1000, file); // scale fgets(line, 1000, file); // scale fgets(line, 1000, file); // sizes int w, h, d; sscanf(line, "%d %d %d", &w, &h, &d); fgets(line, 1000, file); // [ ... ] fgets(line, 1000, file); // { ... } fgets(line, 1000, file); // false 3 fgets(line, 1000, file); // colorimage Raster* raster = new Raster(w, h); for (int row = h - 1; row >= 0; --row) { for (int column = 0; column < w; ++column) { int red = gethex(file); int green = gethex(file); int blue = gethex(file); raster->poke( column, row, float(red)/0xff, float(green)/0xff, float(blue)/0xff, 1.0 ); } } raster->flush(); comp = new RasterComp(new RasterRect(raster), filename); } if (compressed) { pclose(file); } else { fclose(file); } return comp; }
static const char* ReadCreator (const char* filename) { char* buf = nil; FILE* file = fopen(filename, "r"); if (file != nil) { bool compressed; static char creator[CHARBUFSIZE]; char line[CHARBUFSIZE]; file = CheckCompression(file, filename, compressed); if (!file) { return NULL; } if (fgets(line, CHARBUFSIZE, file) != NULL) { /* Two-byte magic numbers */ switch(*((unsigned short *)line)) { case TIFF1_MAGIC_NUM: case TIFF2_MAGIC_NUM: return ("TIFF"); case SUN_MAGIC_NUM: return ("SUN"); } /* One-byte Magic numbers */ switch (line[0]) { case BM_MAGIC_NUM: return ("BM"); case PBM_MAGIC_NUM: return ("PBM"); case ATK_MAGIC_NUM: return ("ATK"); case MP_MAGIC_NUM: return ("MP"); case X11_MAGIC_NUM: return ("X11"); case PCX_MAGIC_NUM: return ("PCX"); case IFF_MAGIC_NUM: return ("IFF"); case GIF_MAGIC_NUM: return ("GIF"); case RLE_MAGIC_NUM: return ("RLE"); } } else { return NULL; } do { if (sscanf(line, "%%%%Creator: %s", creator)) { buf = creator; break; } else if (strcmp(line, "%%EndComments\n") == 0) { break; } } while (fgets(line, CHARBUFSIZE, file) != NULL); if (compressed) { pclose(file); } else { fclose(file); } } return buf; }
// // save any information required to support calibration // static int Ar9300EepromSave() { ar9300_eeprom_t *mptr; // pointer to data int msize; unsigned char header[compression_header_length], cheader[compression_header_length], before[compression_header_length]; char best[MOUTPUT]; int osize; int it; ar9300_eeprom_t *dptr; int dsize; int first; int last; int ib; int bsize; int breference; int balgorithm; int offset[MVALUE],value[MVALUE]; int overhead; ar9300_eeprom_t xptr; int nextaddress; int major, minor; int ccode,creference,cmajor,cminor,clength; unsigned short checksum; unsigned char csum[2]; int error; int written; int ntry; unsigned char ones[compression_header_length]={0xff,0xff,0xff,0xff}; int status; int calmem; int restored; int trysave; // // get a pointer to the current data structure // mptr=Ar9300EepromStructGet(); msize=ar9300_eeprom_struct_size(); calmem=SaveMemory; if(calmem==calibration_data_none) { calmem=ar9300_calibration_data_get(AH); } if(calmem==calibration_data_none) { if(ar9300_eeprom_size(AH)>0) { calmem=calibration_data_eeprom; } else if(ar9300_calibration_data_read_flash(AH, 0x1000, header, 1)==AH_TRUE) { calmem=calibration_data_flash; } else { calmem=calibration_data_otp; } } // Calculate Checksum checksum=ar9300_compression_checksum((unsigned char*)mptr,msize); printf("checksum is %x\n",checksum); #if AH_BYTE_ORDER == AH_BIG_ENDIAN // ar9300_eeprom_t *eeprom_ptr; // eeprom_ptr=Ar9300EepromStructGet(); ar9300_eeprom_template_swap(); ar9300_swap_eeprom(mptr); #endif // For AP with flash calibration data storage save structure uncompressed. #ifdef MDK_AP if(calmem==calibration_data_flash) { int fd; int offset; // for(it=0;it<many;it++) // printf("a = %x, data = %x \n",(address-it), buffer[it]); if((fd = open("/dev/caldata", O_RDWR)) < 0) { perror("Could not open flash\n"); status = -1 ; goto return_status; } // First 0x1000 are reserved for ethernet mac address and other config writes. offset = 0x20000+instance*AR9300_EEPROM_SIZE+FLASH_BASE_CALDATA_OFFSET; // Need for boards with more than one radio lseek(fd, offset, SEEK_SET); if (write(fd, mptr, msize) < 1) { perror("\nwrite\n"); status = -2 ; goto return_status; } close(fd); status = msize ; goto return_status; } #endif // // try all of our compression schemes, // starting with the assumption that uncompressed is best // balgorithm=_compress_none; breference= -1; bsize=msize; nextaddress= -1; // // restore the existing eeprom structure to a temporary buffer // because we need it later for several reasons. Returns 0 // if a default template was loaded because there was no data in memory. // Return -1 on error. Otherwise returns the next available address. // #ifdef USE_AQUILA_HAL trysave=ar9300CalibrationDataGet(0); ar9300CalibrationDataSet(0,calmem); #else trysave=AH9300(AH)->calibration_data_try; AH9300(AH)->calibration_data_try = calmem; #endif restored=ar9300_eeprom_restore_internal(AH, &xptr, msize); if(restored==0) { nextaddress= -1; } else { nextaddress=restored; } ar9300_calibration_data_set(AH,calmem); #ifdef USE_AQUILA_HAL ar9300CalibrationDataSet(0,trysave); #else AH9300(AH)->calibration_data_try = trysave; #endif // // do we over write or append // if overwrite, move the starting address to the top of the memory // if((Overwrite && ar9300_eeprom_volatile(AH)) || nextaddress<0) { if(SaveAddress==0) { nextaddress=ar9300_eeprom_base_address(AH); } else { nextaddress=SaveAddress; } } // // if compression is requested or if the uncompressed data won't fit // if(Compress || nextaddress-msize-compression_header_length-compression_checksum_length<=ar9300_eeprom_low_limit(AH)) { // // try difference with each standard default structure // if(TemplateAllowedMany<=0) { for(it=0; it<ar9300_eeprom_struct_default_many(); it++) { dptr=ar9300_eeprom_struct_default(it); dsize=msize; if(dptr!=0 && dsize<MOUTPUT && dsize==msize) { CheckCompression((char *)mptr,msize,(char *)dptr,dptr->template_version,&balgorithm,&breference,&bsize,best,MOUTPUT); } } } else { for(it=0; it<TemplateAllowedMany; it++) { dptr=ar9300_eeprom_struct_default_find_by_id(TemplateAllowed[it]); dsize=msize; if(dptr!=0 && dsize<MOUTPUT && dsize==msize) { CheckCompression((char *)mptr,msize,(char *)dptr,dptr->template_version,&balgorithm,&breference,&bsize,best,MOUTPUT); } } } // // also try difference with existing eeprom if it was restored from memory // if((!(Overwrite && ar9300_eeprom_volatile(AH))) && restored>0 && xptr.eeprom_version==mptr->eeprom_version) { CheckCompression((char *)mptr,msize,(char *)&xptr,reference_current,&balgorithm,&breference,&bsize,best,MOUTPUT); } } // // if the uncompressed size is the smallest, might as well go with it // if(bsize>=msize) { balgorithm=_compress_none; breference= reference_current; bsize=msize; memcpy(best,mptr,msize); // the uncompressed data // // if using OTP we have to find the first free spot. // if using eeprom, we can overwrite // } // // Now we know the best method and we have the data, so write it // ErrorPrint(EepromAlgorithm,balgorithm,breference,bsize,nextaddress); if(bsize>0 || restored==0) { written=0; osize=bsize; ntry=0; while(written==0 && nextaddress-osize-compression_header_length-compression_checksum_length>ar9300_eeprom_low_limit(AH)) { ntry++; if(ntry>3) { ErrorPrint(EepromTooMany); status = -2; goto return_status; } // // read the spot where we're going to write the header // this is so we can check on error if the chip managed to write anything at all // (void)ar9300_calibration_data_read_array(AH,nextaddress,(unsigned char*)before,compression_header_length); // // create and write header // major=NartVersionMajor(); minor=NartVersionMinor(); CompressionHeaderPack(header, balgorithm, breference, bsize, major, minor); error=CalibrationDataWriteAndVerify(nextaddress,header,compression_header_length); if(error==0) { // // write data // nextaddress-=compression_header_length; error=CalibrationDataWriteAndVerify(nextaddress,(unsigned char*)best,osize); nextaddress-=osize; if(error==0) { // // create and write checksum // checksum=ar9300_compression_checksum((unsigned char*)best,bsize); csum[0]=checksum&0xff; csum[1]=(checksum>>8)&0xff; error=CalibrationDataWriteAndVerify(nextaddress,csum,compression_checksum_length); nextaddress-=compression_checksum_length; if(error==0) { // // everything written successfully, so we're done // written=1; } else { // // and try again // } } else {
void CArchiveScanner::ScanArchive(const std::string& fullName, bool doChecksum) { const std::string fn = FileSystem::GetFilename(fullName); const std::string fpath = FileSystem::GetDirectory(fullName); const std::string lcfn = StringToLower(fn); // Stat file struct stat info = {0}; int statfailed = stat(fullName.c_str(), &info); // If stat fails, assume the archive is not broken nor cached if (!statfailed) { // Determine whether this archive has earlier be found to be broken std::map<std::string, BrokenArchive>::iterator bai = brokenArchives.find(lcfn); if (bai != brokenArchives.end()) { if ((unsigned)info.st_mtime == bai->second.modified && fpath == bai->second.path) { bai->second.updated = true; return; } } // Determine whether to rely on the cached info or not std::map<std::string, ArchiveInfo>::iterator aii = archiveInfos.find(lcfn); if (aii != archiveInfos.end()) { // This archive may have been obsoleted, do not process it if so if (!aii->second.replaced.empty()) { return; } if ((unsigned)info.st_mtime == aii->second.modified && fpath == aii->second.path) { // cache found update checksum if wanted aii->second.updated = true; if (doChecksum && (aii->second.checksum == 0)) { aii->second.checksum = GetCRC(fullName); } return; } else { if (aii->second.updated) { const std::string filename = aii->first; LOG_L(L_ERROR, "Found a \"%s\" already in \"%s\", ignoring.", fullName.c_str(), (aii->second.path + aii->second.origName).c_str()); if (IsBaseContent(filename)) { throw user_error(std::string("duplicate base content detected:\n\t") + aii->second.path + std::string("\n\t") + fpath + std::string("\nPlease fix your configuration/installation as this can cause desyncs!")); } return; } // If we are here, we could have invalid info in the cache // Force a reread if it is a directory archive (.sdd), as // st_mtime only reflects changes to the directory itself, // not the contents. archiveInfos.erase(aii); } } } boost::scoped_ptr<IArchive> ar(archiveLoader.OpenArchive(fullName)); if (!ar || !ar->IsOpen()) { LOG_L(L_WARNING, "Unable to open archive: %s", fullName.c_str()); // record it as broken, so we don't need to look inside everytime BrokenArchive& ba = brokenArchives[lcfn]; ba.path = fpath; ba.modified = info.st_mtime; ba.updated = true; ba.problem = "Unable to open archive"; return; } std::string error; std::string mapfile; const bool hasModinfo = ar->FileExists("modinfo.lua"); const bool hasMapinfo = ar->FileExists("mapinfo.lua"); ArchiveInfo ai; auto& ad = ai.archiveData; if (hasMapinfo) { ScanArchiveLua(ar.get(), "mapinfo.lua", ai, error); if (ad.GetMapFile().empty()) { LOG_L(L_WARNING, "%s: mapfile isn't set in mapinfo.lua, please set it for faster loading!", fullName.c_str()); mapfile = SearchMapFile(ar.get(), error); } } else if (hasModinfo) { ScanArchiveLua(ar.get(), "modinfo.lua", ai, error); } else { mapfile = SearchMapFile(ar.get(), error); } CheckCompression(ar.get(), fullName, error); if (!error.empty()) { // for some reason, the archive is marked as broken LOG_L(L_WARNING, "Failed to scan %s (%s)", fullName.c_str(), error.c_str()); // record it as broken, so we don't need to look inside everytime BrokenArchive& ba = brokenArchives[lcfn]; ba.path = fpath; ba.modified = info.st_mtime; ba.updated = true; ba.problem = error; return; } if (hasMapinfo || !mapfile.empty()) { // it is a map if (ad.GetName().empty()) { // FIXME The name will never be empty, if version is set (see HACK in ArchiveData) ad.SetInfoItemValueString("name_pure", FileSystem::GetBasename(mapfile)); ad.SetInfoItemValueString("name", FileSystem::GetBasename(mapfile)); } if (ad.GetMapFile().empty()) { ad.SetInfoItemValueString("mapfile", mapfile); } AddDependency(ad.GetDependencies(), "Map Helper v1"); ad.SetInfoItemValueInteger("modType", modtype::map); LOG_S(LOG_SECTION_ARCHIVESCANNER, "Found new map: %s", ad.GetNameVersioned().c_str()); } else if (hasModinfo) { // it is a game if (ad.GetModType() == modtype::primary) { AddDependency(ad.GetDependencies(), "Spring content v1"); } LOG_S(LOG_SECTION_ARCHIVESCANNER, "Found new game: %s", ad.GetNameVersioned().c_str()); } else { // neither a map nor a mod: error error = "missing modinfo.lua/mapinfo.lua"; } ai.path = fpath; ai.modified = info.st_mtime; ai.origName = fn; ai.updated = true; ai.checksum = (doChecksum) ? GetCRC(fullName) : 0; archiveInfos[lcfn] = ai; }
//--------------------------------------------------------------------------- // Open an image store - this determines the type of the store and whether // or not NT open functions are available and then decides the best way // to open the target. // bool __fastcall TImageStore::Open(void) { FGeometry.Bytes = (unsigned long long)0; FGeometry.BytesPerSector = (unsigned long long)0; switch (FType) { case isFile: { /// TODO handle Access var, createmode, shareMode int flags = O_NOCTTY |O_LARGEFILE; if (bWriteAccess) { flags |= O_WRONLY|O_CREAT|O_TRUNC; } else { flags |= O_RDONLY; } hHandle = open(FFileName.c_str(), flags); if (hHandle > 0) { if (!bWriteAccess) { //LONGLONG Pos; //Pos = lseek (hHandle, 0, SEEK_CUR); FGeometry.Bytes = lseek (hHandle, 0, SEEK_END); lseek (hHandle, 0, SEEK_SET); CheckCompression(); } else FGeometry.Bytes = 0; //-1; FGeometry.BytesPerSector = 0; FGeometry.BytesPerCluster = 0; } else return false; break; } // case isFile: case isDrive: { struct hd_geometry geom; double MBsize = 0; /// TODO handle Access var, createmode, shareMode int flags = O_NOCTTY | O_SYNC | O_LARGEFILE; if (bWriteAccess) { flags |= O_WRONLY; } else { flags |= O_RDONLY; } hHandle = open(FFileName.c_str(), flags); if (hHandle > 0) { //DeviceIoControl(hHandle, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &PartitionInfo, sizeof(PartitionInfo), &Dummy, NULL); //DeviceIoControl(hHandle, IOCTL_DISK_GET_DRIVE_GEOMETRY , NULL, 0, &DiskGeometry, sizeof(DiskGeometry), &Dummy, NULL); /* get C/H/S geometry and size of partition */ if(ioctl(hHandle, HDIO_GETGEO, &geom) < 0) printf("HDIO_GETGEO ioctl failed"); /* get size of block */ if(ioctl(hHandle, BLKSSZGET, &FGeometry.BytesPerSector) < 0) printf("BLKSSZGET ioctl failed"); /* get size of the partition, chould match C*H*S */ if(ioctl(hHandle, BLKGETSIZE, &FGeometry.NumbSectors) < 0) printf("BLKGETSIZE ioctl failed"); // TODO FGeometry.Bytes = (unsigned long long)FGeometry.NumbSectors * (unsigned long long)FGeometry.BytesPerSector; MBsize = ( FGeometry.NumbSectors)/(1024 * 1024 / FGeometry.BytesPerSector); #ifdef DEBUG_PARTSIZE printf("\n"); if (MBsize > 1024) printf(" Geometry for %s, size = %.2f Gb\n", FFileName.c_str(), (float) (MBsize/1024)); else printf(" Geometry for %s, size = %.2f Mb\n", FFileName.c_str(), (float) MBsize); printf("\t Cylinders: %d\n", geom.cylinders); printf("\t Heads: %d\n", geom.heads); printf("\t Sectors: %d\n", geom.sectors); printf("\t Total sectors: %lu\n", (long unsigned) FGeometry.NumbSectors); printf("\t First sector: %lu\n", geom.start); printf("\t Last sector: %lu\n", (long unsigned) (geom.start + FGeometry.NumbSectors - 1)); printf("\n\n\n"); printf("\t BytesPerSector: %i\n", FGeometry.BytesPerSector); printf("\t PartitionLength: %i\n", (int)FGeometry.NumbSectors); printf("\t Bytes: %llu\n", FGeometry.Bytes); printf("\n"); #endif } else return false; /// TODO enable check compression //CheckFileSystem(); break; } // case isDrive: default: // ERROR return false; break; } // switch (Type) return true; } // bool __fastcall TImageStore::Open(void)
//--------------------------------------------------------------------------- // Open an image store - this determines the type of the store and whether // or not NT open functions are available and then decides the best way // to open the target. // bool __fastcall TImageStore::Open(void) { FGeometry.Bytes = (unsigned long long)0; FGeometry.BytesPerSector = (unsigned long long)0; bool bSuccess; switch (FType) { case isFile: { LARGE_INTEGER nnFileSize; DWORD ShareMode = FILE_SHARE_READ;//(bWriteAccess?0:FILE_SHARE_READ); DWORD CreateMode = (bWriteAccess?CREATE_ALWAYS:OPEN_EXISTING); DWORD Access = GENERIC_READ | (bWriteAccess?GENERIC_WRITE:0); hHandle = CreateFile(FFileName.c_str(), Access, ShareMode, NULL, CreateMode, FILE_ATTRIBUTE_NORMAL, NULL); if (hHandle != INVALID_HANDLE_VALUE) { if (!bWriteAccess) { nnFileSize.LowPart = GetFileSize(hHandle, (unsigned long *)&nnFileSize.HighPart); FGeometry.Bytes = nnFileSize.QuadPart; CheckCompression(); } else FGeometry.Bytes = 0; //-1; FGeometry.BytesPerSector = 0; FGeometry.BytesPerCluster = 0; } else return false; break; } // case isFile: case isDrive: { PARTITION_INFORMATION PartitionInfo; DISK_GEOMETRY DiskGeometry; DWORD Dummy; // A example for a valid file name is: \\.\C DWORD Access = GENERIC_READ | (bWriteAccess?GENERIC_WRITE:0); DWORD ShareMode = (bWriteAccess?0:FILE_SHARE_READ|FILE_SHARE_WRITE); if (HaveNTCalls ) { wchar_t wFileName[255]; int pos = 0; for (pos = 0; pos < FFileName.size(); pos++) { wFileName[pos] = FFileName[pos]; wFileName[pos+1] = L'\0'; } hHandle = NTOpen(wFileName, SYNCHRONIZE | Access, FILE_ATTRIBUTE_NORMAL, ShareMode, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY); } else { if (strncmp ("\\Device\\Floppy", FFileName.c_str(), 14) == 0) { printf ("Make open floppy fail\n"); return false; } printf ("%s line %i: Try to open %s\n", __FILE__, __LINE__, FFileName.c_str()); hHandle = CreateFile(FFileName.c_str(), GENERIC_READ, ShareMode, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_BACKUP_SEMANTICS, NULL); } if (hHandle != INVALID_HANDLE_VALUE) { bSuccess = DeviceIoControl(hHandle, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &PartitionInfo, sizeof(PartitionInfo), &Dummy, NULL); if (!bSuccess) { Close(); return false; } bSuccess = DeviceIoControl(hHandle, IOCTL_DISK_GET_DRIVE_GEOMETRY , NULL, 0, &DiskGeometry, sizeof(DiskGeometry), &Dummy, NULL); if (!bSuccess) { Close(); return false; } FGeometry.Bytes = (unsigned long long)PartitionInfo.PartitionLength.QuadPart; FGeometry.BytesPerSector = DiskGeometry.BytesPerSector; #ifdef DEBUG_PARTSIZE printf("Bytes: %llu\n", FGeometry.Bytes); if ( FGeometry.Bytes == (__uint64)0) printf ("Hallo\n"); #endif #if 0 // Check to see if we're dealing with a floppy. Does anyone have one any more? if (FFileName.Pos("Floppy") || FileName.Pos("A:") || FileName.Pos("B:")) FGeometry.Bytes = DiskGeometry.Cylinders.QuadPart * DiskGeometry.TracksPerCylinder * DiskGeometry.SectorsPerTrack * DiskGeometry.BytesPerSector; #endif } else { printf ("invalid file handle\n"); return false; } #if 0 CheckFileSystem(); #endif break; } // case isDrive: case isNBD: { printf ("%s line %i: Here\n", __FILE__, __LINE__); return false; #ifdef _WIN32 #if 0 AnsiString Host; int nPort = 0; SplitConnectionString(FFileName, Host, nPort); if (NBDConnection) delete NBDConnection; NBDConnection = new TNBDClient(NULL); NBDConnection->Host = Host; NBDConnection->Port = nPort; NBDConnection->Timeout = SelfImageConfig->Values["NBDTimeout"]; NBDConnection->TransactionSize = SelfImageConfig->Values["NBDTransactionSize"] * 1024; NBDConnection->Open(); FGeometry.Bytes = NBDConnection->Size; CheckFileSystem(); #endif #endif } // case isNBD: default: // ERROR return false; break; } // switch (Type) return (hHandle != INVALID_HANDLE_VALUE); } // bool __fastcall TImageStore::Open(void)
//------------------------------------------------------------------------------------ // запись данных в VFS //------------------------------------------------------------------------------------ int vw_WriteIntoVFSfromMemory(const char *Name, const BYTE * buffer, int size) { // (!) пока работаем только с одной открытой VFS в системе, собственно больше и не нужно eVFS *WritebleVFS = StartVFS; if (WritebleVFS == 0) { fprintf(stderr, "Can't find VFS opened for write\n"); return -1; } // Начальная подготовка структуры списка для новых данных eVFS_Entry *NewVFS_Entry = 0; NewVFS_Entry = new eVFS_Entry; if (NewVFS_Entry == 0) return -1; // первый в списке... if (EndVFSArray == 0) { NewVFS_Entry->Prev = 0; NewVFS_Entry->Next = 0; StarVFSArray = NewVFS_Entry; EndVFSArray = NewVFS_Entry; } else // продолжаем заполнение... { NewVFS_Entry->Prev = EndVFSArray; NewVFS_Entry->Next = 0; EndVFSArray->Next = NewVFS_Entry; EndVFSArray = NewVFS_Entry; } NewVFS_Entry->Parent = WritebleVFS; NewVFS_Entry->ArhKeyLen = 0; NewVFS_Entry->ArhKey = 0; NewVFS_Entry->NameLen = (DWORD)strlen(Name); NewVFS_Entry->Name = 0; NewVFS_Entry->Name = new char[NewVFS_Entry->NameLen+1]; strcpy(NewVFS_Entry->Name, Name); NewVFS_Entry->Link = false; NewVFS_Entry->Offset = WritebleVFS->HeaderOffsetVFS; // т.к. это будет последний файл в структуре... NewVFS_Entry->Length = size; NewVFS_Entry->RealLength = size; // надо составлять свою ArhKeyVFS // 0 - 0 int BestMode = 0; #ifdef compression int BestSize = NewVFS_Entry->Length; int TmpSize = 0; // 1 - 1 NewVFS_Entry->ArhKey = new char[1+1]; NewVFS_Entry->ArhKey[0] = '1'; NewVFS_Entry->ArhKey[1] = 0; TmpSize = CheckCompression(NewVFS_Entry->Length, buffer, NewVFS_Entry->ArhKey); if (TmpSize<BestSize) { BestMode = 1; BestSize = TmpSize; } // 2 - 2 if (NewVFS_Entry->ArhKey != 0){delete [] NewVFS_Entry->ArhKey; NewVFS_Entry->ArhKey = 0;} NewVFS_Entry->ArhKey = new char[1+1]; NewVFS_Entry->ArhKey[0] = '2'; NewVFS_Entry->ArhKey[1] = 0; TmpSize = CheckCompression(NewVFS_Entry->Length, buffer, NewVFS_Entry->ArhKey); if (TmpSize<BestSize) { BestMode = 2; BestSize = TmpSize; } // 3 - 12 if (NewVFS_Entry->ArhKey != 0){delete [] NewVFS_Entry->ArhKey; NewVFS_Entry->ArhKey = 0;} NewVFS_Entry->ArhKey = new char[2+1]; NewVFS_Entry->ArhKey[0] = '1'; NewVFS_Entry->ArhKey[0] = '2'; NewVFS_Entry->ArhKey[1] = 0; TmpSize = CheckCompression(NewVFS_Entry->Length, buffer, NewVFS_Entry->ArhKey); if (TmpSize<BestSize) { BestMode = 3; BestSize = TmpSize; } // 4 - 21 if (NewVFS_Entry->ArhKey != 0){delete [] NewVFS_Entry->ArhKey; NewVFS_Entry->ArhKey = 0;} NewVFS_Entry->ArhKey = new char[2+1]; NewVFS_Entry->ArhKey[0] = '2'; NewVFS_Entry->ArhKey[0] = '1'; NewVFS_Entry->ArhKey[1] = 0; TmpSize = CheckCompression(NewVFS_Entry->Length, buffer, NewVFS_Entry->ArhKey); if (TmpSize<BestSize) { BestMode = 4; BestSize = TmpSize; } #endif // compression if (NewVFS_Entry->ArhKey != 0){delete [] NewVFS_Entry->ArhKey; NewVFS_Entry->ArhKey = 0;} switch (BestMode) { default: // по умолчанию (0), или если неверный номер, не используем сжатие NewVFS_Entry->ArhKeyLen = 2; NewVFS_Entry->ArhKey = new char[NewVFS_Entry->ArhKeyLen]; NewVFS_Entry->ArhKey[0] = '0'; NewVFS_Entry->ArhKey[1] = 0; break; case 1: NewVFS_Entry->ArhKeyLen = 2; NewVFS_Entry->ArhKey = new char[NewVFS_Entry->ArhKeyLen]; NewVFS_Entry->ArhKey[0] = '1'; NewVFS_Entry->ArhKey[1] = 0; break; case 2: NewVFS_Entry->ArhKeyLen = 2; NewVFS_Entry->ArhKey = new char[NewVFS_Entry->ArhKeyLen]; NewVFS_Entry->ArhKey[0] = '2'; NewVFS_Entry->ArhKey[1] = 0; break; case 3: NewVFS_Entry->ArhKeyLen = 3; NewVFS_Entry->ArhKey = new char[NewVFS_Entry->ArhKeyLen]; NewVFS_Entry->ArhKey[0] = '1'; NewVFS_Entry->ArhKey[1] = '2'; NewVFS_Entry->ArhKey[2] = 0; break; case 4: NewVFS_Entry->ArhKeyLen = 3; NewVFS_Entry->ArhKey = new char[NewVFS_Entry->ArhKeyLen]; NewVFS_Entry->ArhKey[0] = '2'; NewVFS_Entry->ArhKey[1] = '1'; NewVFS_Entry->ArhKey[2] = 0; break; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // если используется сжатие - запаковываем данные //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // устанавливаем данные BYTE *dstVFS = 0; BYTE *srcVFS = 0; srcVFS = new BYTE[NewVFS_Entry->Length]; memcpy(srcVFS, buffer, NewVFS_Entry->Length); int ssizeVFS = NewVFS_Entry->Length; if (!((NewVFS_Entry->ArhKey[0]=='0')&(strlen(NewVFS_Entry->ArhKey)==1))) { // цикл по кол-ву примененных методов сжатия в ArhKeyVFS for (unsigned int i=0; i<strlen(NewVFS_Entry->ArhKey);i++) { // находим, какой текущий метод сжатия char S = NewVFS_Entry->ArhKey[strlen(NewVFS_Entry->ArhKey)-i-1]; // если RLE if (S == VFS_DATA_ARH_RLE) { vw_DATAtoRLE(&dstVFS, srcVFS, &NewVFS_Entry->Length, ssizeVFS); delete [] srcVFS; srcVFS = 0; srcVFS = dstVFS; ssizeVFS = NewVFS_Entry->Length; dstVFS = 0; } // если HAFF if (S == VFS_DATA_ARH_HAFF) { vw_DATAtoHAFF(&dstVFS, srcVFS, &NewVFS_Entry->Length, ssizeVFS); delete [] srcVFS; srcVFS = 0; srcVFS = dstVFS; ssizeVFS = NewVFS_Entry->Length; dstVFS = 0; } } } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // пишем данные в VFS //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ SDL_RWseek(WritebleVFS->File, WritebleVFS->HeaderOffsetVFS, SEEK_SET); SDL_RWwrite(WritebleVFS->File, srcVFS, NewVFS_Entry->Length, 1); delete [] srcVFS; srcVFS = 0; // переписывать все ентри, принадлежащие этому вфс файлу, в конец eVFS_Entry *Tmp = StarVFSArray; while (Tmp != 0) { eVFS_Entry *Tmp1 = Tmp->Next; // пишем только файлы (не линки) if ((!Tmp->Link) && (NewVFS_Entry->Parent == WritebleVFS)) { SDL_RWwrite(WritebleVFS->File, &Tmp->ArhKeyLen, 1, 1); if (Tmp->ArhKeyLen > 0) SDL_RWwrite(WritebleVFS->File, Tmp->ArhKey, Tmp->ArhKeyLen, 1); SDL_RWwrite(WritebleVFS->File, &Tmp->NameLen, 2, 1); SDL_RWwrite(WritebleVFS->File, Tmp->Name, Tmp->NameLen, 1); SDL_RWwrite(WritebleVFS->File, &Tmp->Offset, 4, 1); SDL_RWwrite(WritebleVFS->File, &Tmp->Length, 4, 1); SDL_RWwrite(WritebleVFS->File, &Tmp->RealLength, 4, 1); } Tmp = Tmp1; } //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // меняем данные //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ WritebleVFS->HeaderOffsetVFS += NewVFS_Entry->Length; WritebleVFS->HeaderLengthVFS += 1+NewVFS_Entry->ArhKeyLen+2+NewVFS_Entry->NameLen+4+4+4; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // переписываем смещение начала таблицы //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ SDL_RWseek(WritebleVFS->File, WritebleVFS->DataStartOffsetVFS, SEEK_SET); SDL_RWwrite(WritebleVFS->File, &WritebleVFS->HeaderOffsetVFS, 4, 1); SDL_RWwrite(WritebleVFS->File, &WritebleVFS->HeaderLengthVFS, 4, 1); printf("%s file added to VFS.\n", Name); return 0; }
void CArchiveScanner::ScanArchive(const std::string& fullName, bool doChecksum) { unsigned modifiedTime = 0; if (CheckCachedData(fullName, &modifiedTime, doChecksum)) return; isDirty = true; const std::string& fn = FileSystem::GetFilename(fullName); const std::string& fpath = FileSystem::GetDirectory(fullName); const std::string& lcfn = StringToLower(fn); std::unique_ptr<IArchive> ar(archiveLoader.OpenArchive(fullName)); if (ar == nullptr || !ar->IsOpen()) { LOG_L(L_WARNING, "[AS::%s] unable to open archive \"%s\"", __func__, fullName.c_str()); // record it as broken, so we don't need to look inside everytime BrokenArchive& ba = brokenArchives[lcfn]; ba.path = fpath; ba.modified = modifiedTime; ba.updated = true; ba.problem = "Unable to open archive"; // does not count as a scan // numScannedArchives += 1; return; } std::string error; std::string arMapFile; // file in archive with "smf" or "sm3" extension std::string miMapFile; // value for the 'mapfile' key parsed from mapinfo const bool hasModinfo = ar->FileExists("modinfo.lua"); const bool hasMapinfo = ar->FileExists("mapinfo.lua"); ArchiveInfo ai; ArchiveData& ad = ai.archiveData; // execute the respective .lua, otherwise assume this archive is a map if (hasMapinfo) { ScanArchiveLua(ar.get(), "mapinfo.lua", ai, error); if ((miMapFile = ad.GetMapFile()).empty()) { LOG_L(L_WARNING, "[AS::%s] set the 'mapfile' key in mapinfo.lua of archive \"%s\" for faster loading!", __func__, fullName.c_str()); arMapFile = SearchMapFile(ar.get(), error); } } else if (hasModinfo) { ScanArchiveLua(ar.get(), "modinfo.lua", ai, error); } else { arMapFile = SearchMapFile(ar.get(), error); } if (!CheckCompression(ar.get(), fullName, error)) { // for some reason, the archive is marked as broken LOG_L(L_WARNING, "[AS::%s] failed to scan \"%s\" (%s)", __func__, fullName.c_str(), error.c_str()); // record it as broken, so we don't need to look inside everytime BrokenArchive& ba = brokenArchives[lcfn]; ba.path = fpath; ba.modified = modifiedTime; ba.updated = true; ba.problem = error; // does count as a scan numScannedArchives += 1; return; } if (hasMapinfo || !arMapFile.empty()) { // map archive if ((ad.GetName()).empty()) { // FIXME The name will never be empty, if version is set (see HACK in ArchiveData) ad.SetInfoItemValueString("name_pure", FileSystem::GetBasename(arMapFile)); ad.SetInfoItemValueString("name", FileSystem::GetBasename(arMapFile)); } if (miMapFile.empty()) ad.SetInfoItemValueString("mapfile", arMapFile); AddDependency(ad.GetDependencies(), GetMapHelperContentName()); ad.SetInfoItemValueInteger("modType", modtype::map); LOG_S(LOG_SECTION_ARCHIVESCANNER, "Found new map: %s", ad.GetNameVersioned().c_str()); } else if (hasModinfo) { // game or base-type (cursors, bitmaps, ...) archive // babysitting like this is really no longer required if (ad.IsGame() || ad.IsMenu()) AddDependency(ad.GetDependencies(), GetSpringBaseContentName()); LOG_S(LOG_SECTION_ARCHIVESCANNER, "Found new game: %s", ad.GetNameVersioned().c_str()); } else { // neither a map nor a mod: error error = "missing modinfo.lua/mapinfo.lua"; } ai.path = fpath; ai.modified = modifiedTime; ai.origName = fn; ai.updated = true; ai.checksum = (doChecksum) ? GetCRC(fullName) : 0; archiveInfos[lcfn] = ai; numScannedArchives += 1; }
int main(int argc, char **argv) { int retval = 0; char *dparams[2]; int paramc = 0, params = -1; char temp[0x1000]; int done = 0; char *source = NULL; int n = 0; // Acción a realizar int action = ACTION_NONE; if (argc <= 1) { action = ACTION_HELP; setparams(0); } for (n = 1; n <= argc; n++) { char *arg; arg = (n < argc) ? argv[n] : ""; //printf("%s\n", arg); // Muestra la ayuda y sale if (strcmp(arg, "-?") == 0 || strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) { //show_help(); action = ACTION_HELP; setparams(0); } // Modificadores { // Modo raw (sin cabeceras de compresión) if (strcmp(arg, "-r") == 0 || strcmp(arg, "-raw") == 0) { raw = 1; continue; } // Modo silencioso if (strcmp(arg, "-s") == 0) { silent = 1; fclose(stdout); continue; } } // Acciones { if (arg[0] == '-') { int cnt = 1; switch (arg[1]) { // Codificad case 'c': action = ACTION_ENCODE ; setparams(2); break; // Decodificia case 'd': action = ACTION_DECODE ; setparams(2); break; // Comprueba case 't': action = ACTION_TEST ; setparams(1); break; // Crea un perfil de compresión case 'p': action = ACTION_PROFILE; setparams(1); break; // Dumpea el text_buffer inicial case 'b': action = ACTION_BDUMP ; setparams(1); break; default: cnt = 0; break; } if (cnt) { done = 0; modifier = (strlen(arg) >= 3) ? atoi(arg + 2) : 3; continue; } } } if ((n < argc) && (paramc < params)) { dparams[paramc++] = arg; } if (paramc >= params) { show_header_once(); done = 1; switch (action) { case ACTION_ENCODE: if (strcmp(dparams[0], dparams[1]) != 0) { retval |= EncodeFile(dparams[0], dparams[1], raw, modifier); } else { fprintf(stderr, "Can't use same file for input and output\n"); retval |= -1; } break; case ACTION_DECODE: if (strcmp(dparams[0], dparams[1]) != 0) { retval |= DecodeFile(dparams[0], dparams[1], raw, modifier); } else { fprintf(stderr, "Can't use same file for input and output\n"); retval |= -1; } break; case ACTION_PROFILE: if (strlen(arg) < 0x900) { sprintf(temp, "%s.profile", arg); ProfileStart(temp); retval |= DecodeFile(dparams[0], NULL, raw, modifier); ProfileEnd(); } break; case ACTION_BDUMP: DumpTextBuffer(dparams[0]); break; case ACTION_TEST: retval |= CheckCompression(dparams[0], modifier); break; case ACTION_HELP: show_help(); break; default: if (n == argc) { if (paramc == params || params == 0) exit(retval); if (params == -1) show_help(); fprintf(stderr, "Expected %d params, but %d given\n", params, paramc); exit(-1); } fprintf(stderr, "Unknown parameter '%s'\n", arg); exit(-1); break; } paramc = params = 0; action = ACTION_NONE; } } show_header_once(); fprintf(stderr, "Expected %d params, but %d given\n", params, paramc); exit(-1); return 0; }