예제 #1
0
/*
   Concatanate given file arguments to the given output argument.
   Used for a special -concatenate option used for specific 'delegates'.
   The option is not formally documented.

      magick -concatenate files... output

   This is much like the UNIX "cat" command, but for both UNIX and Windows,
   however the last argument provides the output filename.
*/
static MagickBooleanType ConcatenateImages(int argc,char **argv,
     ExceptionInfo *exception )
{
  FILE
    *input,
    *output;

  int
    c;

  register ssize_t
    i;

  output=fopen_utf8(argv[argc-1],"wb");
  if (output == (FILE *) NULL) {
    ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[argc-1]);
    return(MagickFalse);
  }
  for (i=2; i < (ssize_t) (argc-1); i++) {
    input=fopen_utf8(argv[i],"rb");
    if (input == (FILE *) NULL)
      ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[i]);
    for (c=fgetc(input); c != EOF; c=fgetc(input))
      (void) fputc((char) c,output);
    (void) fclose(input);
    (void) remove_utf8(argv[i]);
  }
  (void) fclose(output);
  return(MagickTrue);
}
예제 #2
0
파일: link.c 프로젝트: AnanthaRajuC/CEmu
bool receiveVariableLink(int count, const calc_var_t *vars, const char *file_name) {
    FILE *file;
    calc_var_t var;
    uint16_t header_size = 13, size = 0, checksum = 0;
    int byte;
    file = fopen_utf8(file_name, "w+b");;
    if (!file) return false;
    if (fwrite(header, sizeof header - 1, 1, file) != 1) goto w_err;
    if (fseek(file, 0x37, SEEK_SET))                     goto w_err;
    while (count--) {
        if (!vat_search_find(vars++, &var))              goto w_err;
        if (fwrite(&header_size,       2, 1, file) != 1) goto w_err;
        if (fwrite(&var.size,          2, 1, file) != 1) goto w_err;
        if (fwrite(&var.type,          1, 1, file) != 1) goto w_err;
        if (fwrite(&var.name,          8, 1, file) != 1) goto w_err;
        if (fwrite(&var.version,       1, 1, file) != 1) goto w_err;
        if (fputc(var.archived << 7, file) == EOF)       goto w_err;
        if (fwrite(&var.size,          2, 1, file) != 1) goto w_err;
        if (fwrite(var.data,    var.size, 1, file) != 1) goto w_err;
        size += 17 + var.size;
    }
    if (fseek(file, 0x35, SEEK_SET))                     goto w_err;
    if (fwrite(&size,                  2, 1, file) != 1) goto w_err;
    while ((byte = fgetc(file)) != EOF) {
        checksum += byte;
    }
    if (ferror(file))                                    goto w_err;
    if (fwrite(&checksum,              2, 1, file) != 1) goto w_err;
    return !fclose(file);

  w_err:
    fclose(file);
    remove(file_name);
    return false;
}
예제 #3
0
bool config_file_write(config_file_t *conf, const char *path, bool sort)
{
   if (!string_is_empty(path))
   {
      void* buf  = NULL;
#ifdef ORBIS
      int fd     = orbisOpen(path,O_RDWR|O_CREAT,0644);
      if (fd < 0)
         return false;
      config_file_dump_orbis(conf,fd);
      orbisClose(fd);
#else
      FILE *file = (FILE*)fopen_utf8(path, "wb");
      if (!file)
         return false;

      /* TODO: this is only useful for a few platforms, find which and add ifdef */
#if !defined(PS2) && !defined(PSP)
      buf = calloc(1, 0x4000);
      setvbuf(file, (char*)buf, _IOFBF, 0x4000);
#endif

      config_file_dump(conf, file, sort);

      if (file != stdout)
         fclose(file);
      free(buf);
#endif
   }
   else
      config_file_dump(conf, stdout, sort);

   return true;
}
예제 #4
0
void retro_main_log_file_init(const char *path, bool append)
{
   if (log_file_initialized)
      return;

#ifdef NXLINK
   if (path == NULL && nxlink_connected)
       mutexInit(&nxlink_mtx);
#endif

   log_file_fp          = stderr;
   if (path == NULL)
      return;

   log_file_fp          = (FILE*)fopen_utf8(path, append ? "ab" : "wb");

   if (!log_file_fp)
   {
      log_file_fp       = stderr;
      RARCH_ERR("Failed to open system event log file: %s\n", path);
      return;
   }

   log_file_initialized = true;

#if !defined(PS2) /* TODO: PS2 IMPROVEMENT */
   /* TODO: this is only useful for a few platforms, find which and add ifdef */
   log_file_buf = calloc(1, 0x4000);
   setvbuf(log_file_fp, (char*)log_file_buf, _IOFBF, 0x4000);
#endif
}
예제 #5
0
void RomSelection::openROMSegments() {
    FILE* readSegment;
    QFileDialog dialog(this);
    QStringList fileNames;

    uint8_t tmpBuf[10];
    uint16_t tmp16;
    int tmpint;

    dialog.setDirectory(currentDir);
    dialog.setFileMode(QFileDialog::ExistingFiles);
    dialog.setNameFilter(QStringLiteral("ROMData (*.8xv)"));
    if (!dialog.exec()) {
        return;
    }
    fileNames = dialog.selectedFiles();

    for (int i = 0; i < fileNames.size(); i++) {
        readSegment = fopen_utf8(fileNames.at(i).toStdString().c_str(), "rb");
        if (readSegment) {
            /* make sure the name is right... */
            if (fseek(readSegment,0x3C,0))              goto _someerror;
            if (fread(tmpBuf,1,8,readSegment) != 8)     goto _someerror;

            if (!memcmp(tmpBuf, "ROMData",7)) {

                tmp16 = 0;
                if (fseek(readSegment,0x48,0))          goto _someerror;
                if (fread(&tmp16,2,1,readSegment) != 1) goto _someerror;
                if (segmentROMSize == tmp16) {

                    /* first one is 'A' */
                    tmpint = tmpBuf[7]-'A';
                    if (segmentFilledStatus[tmpint] == false) {
                        segmentFilledStatus[tmpint] = true;

                        if (fread(romArray+(segmentROMSize*tmpint),1,segmentROMSize,readSegment) != segmentROMSize) goto _someerror;
                        ui->progressBar->setValue(ui->progressBar->value()+1);
                    }
                } else {
                    QMessageBox::warning(this, tr("Invalid"), tr("Invalid ROM segment size: ")+fileNames.at(i));
                    fclose(readSegment);
                    return;
                }
            } else {
_someerror:
                QMessageBox::warning(this, tr("Invalid"), tr("Invalid ROM segment: ")+fileNames.at(i));
                fclose(readSegment);
                return;
            }

            fclose(readSegment);
        }
    }
    if (ui->progressBar->value() == numROMSegments) {
        ui->labelHidden->setVisible(true);
        ui->buttonBrowseSave->setVisible(true);
    }
}
예제 #6
0
bool PutFileContents(const Utf8String& utf8Filename, const Utf8String& content)
{
	FILE *stream = fopen_utf8(utf8Filename.c_str(), "wb");
	if(!stream) return false;
	fwrite(content.c_str(), content.length(),1, stream);
	fclose(stream);
	return true;
}
예제 #7
0
파일: utils.cpp 프로젝트: alberthdev/CEmu
bool fileExists(const std::string& path) {
    if (path.empty()) {
        return false;
    }
    if (FILE *file = fopen_utf8(path.c_str(), "r")) {
        fclose(file);
        return true;
    } else {
        return false;
    }
}
예제 #8
0
void xmodem_send(const char *filename) {
    if (xmodem_file)
        fclose(xmodem_file);
    xmodem_file = fopen_utf8(filename, "rb");
    if (!xmodem_file) {
        gui_perror(filename);
        return;
    }
    gui_status_printf("XMODEM: sending file %s...\n", filename);
    xmodem_buf[1] = 0;
    xmodem_next_packet();
}
예제 #9
0
bool emu_suspend(const char *file)
{
    gui_busy_raii gui_busy;

    FILE *fp = fopen_utf8(file, "wb");
    if(!fp)
        return false;

    int dupfd = dup(fileno(fp));
    fclose(fp);
    fp = nullptr;

    // gzdopen takes ownership of the fd
    gzFile gzf = gzdopen(dupfd, "wb");
    if(!gzf)
    {
        close(dupfd);
        return false;
    }

    size_t size = sizeof(emu_snapshot) + flash_suspend_flexsize();
    auto snapshot = (struct emu_snapshot *) malloc(size);
    if(!snapshot)
    {
        gzclose(gzf);
        return false;
    }

    snapshot->product = product;
    snapshot->asic_user_flags = asic_user_flags;
    // TODO: Max length
    strncpy(snapshot->path_boot1, path_boot1.c_str(), sizeof(snapshot->path_boot1) - 1);
    strncpy(snapshot->path_flash, path_flash.c_str(), sizeof(snapshot->path_flash) - 1);

    if(!flash_suspend(snapshot)
            || !cpu_suspend(snapshot)
            || !sched_suspend(snapshot)
            || !memory_suspend(snapshot))
    {
        free(snapshot);
        gzclose(gzf);
        return false;
    }

    snapshot->sig = SNAPSHOT_SIG;
    snapshot->version = SNAPSHOT_VER;

    bool success = (size_t) gzwrite(gzf, snapshot, size) == size;

    free(snapshot);
    gzclose(gzf);
    return success;
}
std::string read_file(const std::string &filename) {
  FILE *in = fopen_utf8(filename, "rb");
  if (!in) return "";
  std::vector<char> buf(1024*1024);
  std::string ret;
  while (1) {
    size_t nread = fread(&buf[0], 1, sizeof(buf), in);
    if (nread <= 0) break;
    ret.append(&buf[0], nread);
  }
  fclose(in);
  return ret;
}
예제 #11
0
/*
   Concatanate given file arguments to the given output argument.
   Used for a special -concatenate option used for specific 'delegates'.
   The option is not formally documented.

      magick -concatenate files... output

   This is much like the UNIX "cat" command, but for both UNIX and Windows,
   however the last argument provides the output filename.
*/
static MagickBooleanType ConcatenateImages(int argc,char **argv,
     ExceptionInfo *exception )
{
  FILE
    *input,
    *output;

  int
    c;

  register ssize_t
    i;

  if (ExpandFilenames(&argc,&argv) == MagickFalse)
    ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
         GetExceptionMessage(errno));

  output=fopen_utf8(argv[argc-1],"wb");
  if (output == (FILE *) NULL) {
    ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[argc-1]);
    return(MagickFalse);
  }
  for (i=2; i < (ssize_t) (argc-1); i++) {
#if 0
    fprintf(stderr, "DEBUG: Concatenate Image: \"%s\"\n", argv[i]);
#endif
    input=fopen_utf8(argv[i],"rb");
    if (input == (FILE *) NULL) {
        ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[i]);
        continue;
      }
    for (c=fgetc(input); c != EOF; c=fgetc(input))
      (void) fputc((char) c,output);
    (void) fclose(input);
    (void) remove_utf8(argv[i]);
  }
  (void) fclose(output);
  return(MagickTrue);
}
예제 #12
0
static void
updatePlaylist(TSMPlaylist * playlist,
               const char * playlistFileName,
               const char * segmentFileName,
               const unsigned int segmentIndex,
               const int segmentDuration)
{
    if (playlist->bufferCapacity > 0)
    {
        /* create a live streaming playlist */
        updateLivePlaylist(playlist,
                           playlistFileName,
                           segmentFileName,
                           segmentIndex,
                           segmentDuration);
    }
    else
    {
        /* append to the existing playlist */
        char tmp[1024] = { 0 };

        if (!playlist->file)
        {
            playlist->file = fopen_utf8(playlistFileName, "w+b");
            snprintf(tmp,
                     sizeof(tmp),
                     "#EXTM3U\n"
                     "#EXT-X-TARGETDURATION:%u\n",
                     playlist->targetDuration);
            fwrite(tmp, strlen(tmp), 1, playlist->file);
        }
        
        if (!playlist->file)
        {
            fprintf(stderr,
                    "Could not open m3u8 index file (%s), "
                    "no index file will be created\n",
                    playlistFileName);
        }
        
        snprintf(tmp,
                 sizeof(tmp),
                 "#EXTINF:%u,\n%s%s\n",
                 segmentDuration,
                 playlist->httpPrefix,
                 segmentFileName);
        fwrite(tmp, strlen(tmp), 1, playlist->file);
        fflush(playlist->file);
    }
}
예제 #13
0
void RomSelection::saveDumpProgram() {
    FILE* save_program;
    QString filename = QFileDialog::getSaveFileName(this, tr("Save ROM Dumper Program"), QString(), tr("ROM Dumper (*.8xp)"));
    if (filename.isEmpty()) {
        return;
    }

    save_program = fopen_utf8(filename.toStdString().c_str(), "w+b");

    if (save_program) {
        fwrite(dumper_program,1,sizeof(dumper_program),save_program);
        fclose(save_program);
    }
}
예제 #14
0
bool RomSelection::checkImageSize(const char *filename) {
    size_t s;

    FILE* rom_read = fopen_utf8(filename, "r+b");

    if (!rom_read) {
        return false;
    }

    fseek(rom_read, 0, SEEK_END);
    s = ftell(rom_read);

    fclose(rom_read);

    return s == totalROMSize;
}
예제 #15
0
void RomSelection::openROMConfig() {
    FILE* romInfo;
    QFileDialog dialog(this);
    QString fileName;

    uint8_t tmpBuf[10];

    dialog.setDirectory(QDir::homePath());
    dialog.setFileMode(QFileDialog::ExistingFile);
    dialog.setNameFilter(QStringLiteral("ROMData0 (*.8xv)"));
    if (!dialog.exec()) {
        return;
    }
    fileName = dialog.selectedFiles().at(0);
    currentDir = dialog.directory();

    romInfo = fopen_utf8(fileName.toStdString().c_str(), "rb");

    if(!romInfo) {
        QMessageBox::warning(this, tr("Opening Error"), tr("Unable to open the file."));
        return;
    }

    if (fseek(romInfo,0x3C,0))          goto _rerr;
    if (fread(tmpBuf,1,8,romInfo) != 8) goto _rerr;

    if (memcmp(tmpBuf,"ROMData0",8)) {
_rerr:
        QMessageBox::warning(this, tr("Invalid"), tr("Invalid ROM data configuration."));
        fclose(romInfo);
        return;
    }

    if (fseek(romInfo,0x4A,0))          goto _rerr;
    if (fread(tmpBuf,1,3,romInfo) != 3) goto _rerr;
    imageSize = static_cast<uint32_t>(tmpBuf[0])    |
                static_cast<uint32_t>(tmpBuf[1]<<8) |
                static_cast<uint32_t>(tmpBuf[2]<<16);

    numROMSegments = (imageSize/segmentROMSize)+1;

    ui->buttonOpenSegments->setEnabled(true);
    ui->progressBar->setMaximum(numROMSegments);
    ui->buttonOpenRomData0->setEnabled(false);
    fclose(romInfo);
}
예제 #16
0
int DllLoader::Parse()
{
  int iResult = 0;

  std::string strFileName= GetFileName();
  FILE* fp = fopen_utf8(CSpecialProtocol::TranslatePath(strFileName).c_str(), "rb");

  if (fp)
  {
    if (CoffLoader::ParseCoff(fp))
    {
      if(WindowsHeader)
        tracker_dll_set_addr(this, (uintptr_t)hModule,
          (uintptr_t)hModule + WindowsHeader->SizeOfImage - 1);
      else
      {
        uintptr_t iMinAddr = std::numeric_limits<uintptr_t>::max();
        uintptr_t iMaxAddr = 0;
        // dll is loaded now, this means we also know the base address of it and its size
        for (int i = 0; i < NumOfSections; ++i)
        {
          iMinAddr = std::min<uintptr_t>(iMinAddr,
                       (uintptr_t)SectionHeader[i].VirtualAddress);
          iMaxAddr = std::max<uintptr_t>(iMaxAddr,
                       (uintptr_t)(SectionHeader[i].VirtualAddress +
                                   SectionHeader[i].VirtualSize));
        }
        if(iMaxAddr > iMinAddr)
        {
          iMinAddr += (uintptr_t)hModule;
          iMaxAddr += (uintptr_t)hModule;
          tracker_dll_set_addr(this, iMinAddr, iMaxAddr - 1);
        }
      }
      LoadExports();
      iResult = 1;
    }
    fclose(fp);
  }
  if (iResult == 0)
  {
    m_bTrack = false;
  }
  return iResult;
}
예제 #17
0
void save_sound_aiff_fl32_file(const char *path, float *snd, size_t sample_count, int channels, int samplerate)
{
	FILE *file;
	uint8_t be80[10];
	size_t i, full_count = sample_count * (size_t) channels;

	if (snd==NULL || sample_count==0)
		return ;

	file = fopen_utf8(path, "wb");
	if (file==NULL)
	{
		fprintf_rl(stderr, "save_sound_aiff_file() couldn't open file '%s' for writing.\n", path);
		return ;
	}

	fprintf(file, "FORM");
	fwrite_BE32(file, 4+12+(8+2+4+2+10+4+18)+(8+8+full_count*sizeof(float)));	// size of the whole file - 8 bytes
	fprintf(file, "AIFC");			// format

	fprintf(file, "FVER");
	fwrite_BE32(file, 4);
	fwrite_BE32(file, 0xA2805140);		// format version (May 23, 1990, 2:40 p.m.)

	fprintf(file, "COMM");
	fwrite_BE32(file, 2+4+2+10+4+18);	// chunk size
	fwrite_BE16(file, channels);
	fwrite_BE32(file, sample_count);
	fwrite_BE16(file, 32);			// bit depth
	double_to_BE80_float(samplerate, be80);
	fwrite(be80, 1, 10, file);		// sample rate
	fprintf(file, "fl32");			// compression
	fprintf(file, "\021IEEE 32-bit float");	// Pascal string (first byte is 17, the length)
	
	fprintf(file, "SSND");
	fwrite_BE32(file, 8+full_count*sizeof(float));	// chunk size
	fwrite_BE32(file, 0);			// not needed
	fwrite_BE32(file, 0);			// not needed

	// write snd in BE 32-bit float
	for (i=0; i < full_count; i++)
		fwrite_BE32(file, float_as_u32(snd[i]));

	fclose(file);
}
예제 #18
0
cl_int build_cl_program_from_file(clctx_t *c, cl_program *program, char *cl_src_path)
{
	const int max_src_size = 32000;
	cl_int ret;
	size_t kernel_code_size;
	FILE *fp;
	char *kernel_src_str;

	fp = fopen_utf8(cl_src_path, "rb");
	kernel_src_str = malloc(max_src_size);
	kernel_code_size = fread(kernel_src_str, 1, max_src_size, fp);
	fclose(fp);

	ret = build_cl_program(c, program, kernel_src_str);

	free(kernel_src_str);

	return ret;
}
예제 #19
0
size_t gzip_filesize(const char *path)
{
    #if __BYTE_ORDER == __LITTLE_ENDIAN
        FILE *fp = fopen_utf8(path, "rb");
        if(!fp)
            return false;

        // The last four bytes of a gzip file are the uncompressed size (% 2^32)
        fseek(fp, -4, SEEK_END);
        uint32_t ret = 0;
        if(fread(&ret, 4, 1, fp) != 1)
            ret = 0;

        fclose(fp);
        return ret;
    #else
        #error "Not implemented"
    #endif
}
예제 #20
0
void retro_main_log_file_init(const char *path)
{
   if (log_file_initialized)
      return;

#ifdef NXLINK
   if (path == NULL && nxlink_connected)
       mutexInit(&nxlink_mtx);
#endif

   log_file_fp          = stderr;
   if (path == NULL)
      return;

   log_file_fp          = (FILE*)fopen_utf8(path, "wb");
   log_file_initialized = true;

   /* TODO: this is only useful for a few platforms, find which and add ifdef */
   log_file_buf = calloc(1, 0x4000);
   setvbuf(log_file_fp, (char*)log_file_buf, _IOFBF, 0x4000);
}
예제 #21
0
  FILE* xbp_fopen(const char *filename, const char *mode)
  {
    //convert '/' to '\\'
    char cName[1024];
    char* p;
    
    strcpy(cName, filename);
    CORRECT_SEP_STR(cName);
    
    //for each "\\..\\" remove the directory before it
    while(p = strstr(cName, "\\..\\"))
    {
      char* file = p + 3;
      *p = '\0';
      *strrchr(cName, '\\') = '\0';
      strcat(cName, file);
    }

    // don't use emulated files, they do not work in python yet
    return fopen_utf8(_P(cName).c_str(), mode);
  }
예제 #22
0
void RomSelection::saveROMImage() {
    FILE* saveRom;
    QString filename = QFileDialog::getSaveFileName(this, tr("Save ROM Image"), QString(), tr("ROM Image (*.rom)"));
    if  (filename.isEmpty()) {
        return;
    }

    romImagePath = filename.toStdString();

    saveRom = fopen_utf8(romImagePath.c_str(), "w+b");

    if (saveRom) {
        /* Make sure the only thing in the rom is the boot+os */
        memset(&romArray[imageSize],0xFF,totalROMSize-imageSize-1);

        fwrite(romArray,1,totalROMSize,saveRom);

        fclose(saveRom);
    }

    close();
}
예제 #23
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   A c q u i r e S c r i p t T o k e n I n f o                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  AcquireScriptTokenInfo() allocated, initializes and opens the given
%  file stream from which tokens are to be extracted.
%
%  The format of the AcquireScriptTokenInfo method is:
%
%     ScriptTokenInfo *AcquireScriptTokenInfo(char *filename)
%
%  A description of each parameter follows:
%
%    o filename   the filename to open  ("-" means stdin)
%
*/
WandExport ScriptTokenInfo *AcquireScriptTokenInfo(char *filename)
{
  ScriptTokenInfo
    *token_info;

  token_info=(ScriptTokenInfo *) AcquireMagickMemory(sizeof(*token_info));
  if (token_info == (ScriptTokenInfo *) NULL)
    return token_info;
  (void) ResetMagickMemory(token_info,0,sizeof(*token_info));

  token_info->opened=MagickFalse;
  if ( LocaleCompare(filename,"-") == 0 ) {
    token_info->stream=stdin;
    token_info->opened=MagickFalse;
  }
  else if ( LocaleNCompare(filename,"fd:",3) == 0 ) {
    token_info->stream=fdopen(StringToLong(filename+3),"r");
    token_info->opened=MagickFalse;
  }
  else {
    token_info->stream=fopen_utf8(filename, "r");
  }
  if ( token_info->stream == (FILE *)NULL ) {
    token_info=(ScriptTokenInfo *) RelinquishMagickMemory(token_info);
    return(token_info);
  }

  token_info->curr_line=1;
  token_info->length=INITAL_TOKEN_LENGTH;
  token_info->token=(char *) AcquireMagickMemory(token_info->length);

  token_info->status=(token_info->token != (char *)NULL)
                      ? TokenStatusOK : TokenStatusMemoryFailed;
  token_info->signature=WandSignature;

  return token_info;
}
예제 #24
0
파일: emu.c 프로젝트: alberthdev/CEmu
bool emu_save(const char *file) {
    FILE *savedImage = NULL;
    emu_image_t *image = NULL;
    size_t size = sizeof(emu_image_t);
    bool success = false;

    savedImage = fopen_utf8(file, "wb");
    if (!savedImage) {
        return false;
    }

    image = (emu_image_t*)malloc(size);

    gui_set_busy(true);

    do {
        if (!image) {
            break;
        }

        if (!asic_save(image)) {
            break;
        }

        image->version = imageVersion;

        success = (fwrite(image, 1, size, savedImage) == size);
    } while(0);

    free(image);
    fclose(savedImage);

    gui_set_busy(false);

    return success;
}
예제 #25
0
bool ReadUtf8TextFile(Utf8String utf8Filename, Utf8String& data)
{
	FILE *stream = fopen_utf8(utf8Filename.c_str(), "rb");
	if(!stream) return false;
        long size = getFileSize(utf8Filename);
	unsigned char buf[3];
	fread(buf, 1, 3, stream);	


	if(buf[0] == 0xEF || buf[1] == 0xBB || buf[2] == 0xBF) // UTF8 Byte Order Mark (BOM)
	{	
		size -= 3;	
	}
	else if(buf[0] == 0xFF || buf[1] == 0xFE ) {
		// UTF-16LE encoding
		size -= 2;
		fseek( stream, 2L,  SEEK_SET );
		std::wstring res;
		int charCount = size/2;
		res.resize(charCount);
		size_t charsRead = fread(&res[0], 2, charCount, stream);	
		res[charsRead]=0;
		fclose(stream);
		data = WstringToUtf8(res);
		return true;
	} 
	else {
		// no BOM was found; seeking backward
		fseek( stream, 0L,  SEEK_SET );
	}
	data.resize(size + 1);
	size_t bytesRead = fread(&data[0], 1, size, stream);	
	data[bytesRead] = 0;
	fclose(stream);
	return true;
}
예제 #26
0
bool config_file_write(config_file_t *conf, const char *path)
{
   if (!string_is_empty(path))
   {
      void* buf  = NULL;
      FILE *file = (FILE*)fopen_utf8(path, "wb");
      if (!file)
         return false;

      /* TODO: this is only useful for a few platforms, find which and add ifdef */
      buf = calloc(1, 0x4000);
      setvbuf(file, (char*)buf, _IOFBF, 0x4000);

      config_file_dump(conf, file);

      if (file != stdout)
         fclose(file);
      free(buf);
   }
   else
      config_file_dump(conf, stdout);

   return true;
}
예제 #27
0
//----------------------------------------------------------------
// main_utf8
// 
int main_utf8(int argc, char **argv)
{
    const char *input = NULL;
    const char *output_prefix = "";
    double target_segment_duration = 0.0;
    char *segment_duration_check = NULL;
    const char *playlist_filename = NULL;
    const char *http_prefix = "";
    long max_tsfiles = 0;
    char *max_tsfiles_check = NULL;
    double prev_segment_time = 0.0;
    double segment_duration = 0.0;
    unsigned int output_index = 0;
    const AVClass *fc = avformat_get_class();
    AVDictionary *format_opts = NULL;
    AVOutputFormat *ofmt = NULL;
    AVFormatContext *ic = NULL;
    AVFormatContext *oc = NULL;
    AVStream *video_st = NULL;
    AVStream *audio_st = NULL;
    AVCodec *codec = NULL;
    char *output_filename = NULL;
    char *pid_filename = NULL;
    int video_index = -1;
    int audio_index = -1;
    int kill_file = 0;
    int decode_done = 0;
    int ret = 0;
    int i = 0;
    TSMStreamLace * streamLace = NULL;
    TSMPlaylist * playlist = NULL;
    const double segment_duration_error_tolerance = 0.05;
    double extra_duration_needed = 0;
    int strict_segment_duration = 0;
    
    av_log_set_level(AV_LOG_INFO);
    
    for (int i = 1; i < argc; i++)
    {
        if (strcmp(argv[i], "-i") == 0)
        {
            if ((argc - i) <= 1) usage(argv, "could not parse -i parameter");
            i++;
            input = argv[i];
        }
        else if (strcmp(argv[i], "-o") == 0)
        {
            if ((argc - i) <= 1) usage(argv, "could not parse -i parameter");
            i++;
            output_prefix = argv[i];
        }
        else if (strcmp(argv[i], "-d") == 0)
        {
            if ((argc - i) <= 1) usage(argv, "could not parse -d parameter");
            i++;
            
            target_segment_duration = strtod(argv[i], &segment_duration_check);
            if (segment_duration_check == argv[i] ||
                target_segment_duration == HUGE_VAL ||
                target_segment_duration == -HUGE_VAL)
            {
                usage3(argv, "invalid segment duration: ", argv[i]);
            }
        }
        else if (strcmp(argv[i], "-x") == 0)
        {
            if ((argc - i) <= 1) usage(argv, "could not parse -x parameter");
            i++;
            playlist_filename = argv[i];
        }
        else if (strcmp(argv[i], "-p") == 0)
        {
            if ((argc - i) <= 1) usage(argv, "could not parse -p parameter");
            i++;
            http_prefix = argv[i];
        }
        else if (strcmp(argv[i], "-w") == 0)
        {
            if ((argc - i) <= 1) usage(argv, "could not parse -w parameter");
            i++;

            max_tsfiles = strtol(argv[i], &max_tsfiles_check, 10);
            if (max_tsfiles_check == argv[i] ||
                max_tsfiles < 0 ||
                max_tsfiles >= INT_MAX)
            {
                usage3(argv, "invalid live stream max window size: ", argv[i]);
            }
        }
        else if (strcmp(argv[i], "-P") == 0)
        {
            if ((argc - i) <= 1) usage(argv, "could not parse -P parameter");
            i++;
            pid_filename = argv[i];
        }
        else if (strcmp(argv[i], "--watch-for-kill-file") == 0)
        {
            // end program when it finds a file with name 'kill':
            kill_file = 1;
        }
        else if (strcmp(argv[i], "--strict-segment-duration") == 0)
        {
            // force segment creation on non-keyframe boundaries:
            strict_segment_duration = 1;
        }
        else if (strcmp(argv[i], "--avformat-option") == 0)
        {
            const AVOption *of;
            const char *opt;
            const char *arg;
            if ((argc - i) <= 1) usage(argv, "could not parse --avformat-option parameter");
            i++;
            opt = argv[i];
            if ((argc - i) <= 1) usage(argv, "could not parse --avformat-option parameter");
            i++;
            arg = argv[i];

            if ((of = av_opt_find(&fc, opt, NULL, 0,
                                  AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)))
                av_dict_set(&format_opts, opt, arg, (of->type == AV_OPT_TYPE_FLAGS) ? AV_DICT_APPEND : 0);
            else
                usage3(argv, "unknown --avformat-option parameter: ", opt);
        }
        else if (strcmp(argv[i], "--loglevel") == 0)
        {
            const char *arg;
            if ((argc - i) <= 1) usage(argv, "could not parse --loglevel parameter");
            i++;
            arg = argv[i];

            if (loglevel(arg))
                usage3(argv, "unknown --loglevel parameter: ", arg);
        }
    }
    
    if (!input)
    {
        usage(argv, "-i input file parameter must be specified");
    }
    
    if (!playlist_filename)
    {
        usage(argv, "-x m3u8 playlist file parameter must be specified");
    }
    
    if (target_segment_duration == 0.0)
    {
        usage(argv, "-d segment duration parameter must be specified");
    }
    
    // Create PID file
    if (pid_filename)
    {
        FILE* pid_file = fopen_utf8(pid_filename, "wb");
        if (pid_file)
        {
            fprintf(pid_file, "%d", getpid());
            fclose(pid_file);
        }
    }

    av_register_all();
    avformat_network_init();

    if (!strcmp(input, "-")) {
        input = "pipe:";
    }
    
    output_filename = malloc(sizeof(char) * (strlen(output_prefix) + 15));
    if (!output_filename) {
        fprintf(stderr, "Could not allocate space for output filenames\n");
        goto error;
    }

    playlist = createPlaylist(max_tsfiles,
                              target_segment_duration,
                              http_prefix);
    if (!playlist)
    {
        fprintf(stderr, "Could not allocate space for m3u8 playlist structure\n");
        goto error;
    }

    ret = avformat_open_input(&ic, input, NULL, (format_opts) ? &format_opts : NULL);
    if (ret != 0) {
        fprintf(stderr, "Could not open input file, make sure it is an mpegts or mp4 file: %d\n", ret);
        goto error;
    }
    av_dict_free(&format_opts);

    if (avformat_find_stream_info(ic, NULL) < 0) {
        fprintf(stderr, "Could not read stream information\n");
        goto error;
    }

#if LIBAVFORMAT_VERSION_MAJOR > 52 || (LIBAVFORMAT_VERSION_MAJOR == 52 && \
                                       LIBAVFORMAT_VERSION_MINOR >= 45)
    ofmt = av_guess_format("mpegts", NULL, NULL);
#else
    ofmt = guess_format("mpegts", NULL, NULL);
#endif
    
    if (!ofmt) {
        fprintf(stderr, "Could not find MPEG-TS muxer\n");
        goto error;
    }

    oc = avformat_alloc_context();
    if (!oc) {
        fprintf(stderr, "Could not allocated output context\n");
        goto error;
    }
    oc->oformat = ofmt;

    video_index = -1;
    audio_index = -1;

    for (i = 0; i < ic->nb_streams && (video_index < 0 || audio_index < 0); i++) {
        switch (ic->streams[i]->codec->codec_type) {
            case AVMEDIA_TYPE_VIDEO:
                video_index = i;
                ic->streams[i]->discard = AVDISCARD_NONE;
                video_st = add_output_stream(oc, ic->streams[i]);
                break;
            case AVMEDIA_TYPE_AUDIO:
                audio_index = i;
                ic->streams[i]->discard = AVDISCARD_NONE;
                audio_st = add_output_stream(oc, ic->streams[i]);
                break;
            default:
                ic->streams[i]->discard = AVDISCARD_ALL;
                break;
        }
    }

    av_dump_format(oc, 0, output_prefix, 1);
    
    if (video_index >=0) {
      codec = avcodec_find_decoder(video_st->codec->codec_id);
      if (!codec) {
        fprintf(stderr, "Could not find video decoder, key frames will not be honored\n");
      }

      if (avcodec_open2(video_st->codec, codec, NULL) < 0) {
        fprintf(stderr, "Could not open video decoder, key frames will not be honored\n");
      }
    }

    snprintf(output_filename, strlen(output_prefix) + 15, "%s-%u.ts", output_prefix, ++output_index);
    if (avio_open(&oc->pb, output_filename, AVIO_FLAG_WRITE) < 0) {
        fprintf(stderr, "Could not open '%s'\n", output_filename);
        goto error;
    }

    if (avformat_write_header(oc, NULL)) {
        fprintf(stderr, "Could not write mpegts header to first output file\n");
        goto error;
    }

    prev_segment_time = (double)(ic->start_time) / (double)(AV_TIME_BASE);

    streamLace = createStreamLace(ic->nb_streams);
    
    do {
        double segment_time = 0.0;
        AVPacket packet;
        double packetStartTime = 0.0;
        double packetDuration = 0.0;
        
        if (!decode_done)
        {
            decode_done = av_read_frame(ic, &packet);
            if (!decode_done)
            {
                if (packet.stream_index != video_index &&
                    packet.stream_index != audio_index)
                {
                    av_free_packet(&packet);
                    continue;
                }
                
                double timeStamp = 
                    (double)(packet.pts) * 
                    (double)(ic->streams[packet.stream_index]->time_base.num) /
                    (double)(ic->streams[packet.stream_index]->time_base.den);
                
                if (av_dup_packet(&packet) < 0)
                {
                    fprintf(stderr, "Could not duplicate packet\n");
                    av_free_packet(&packet);
                    break;
                }
                
                insertPacket(streamLace, &packet, timeStamp);
            }
        }
        
        if (countPackets(streamLace) < 50 && !decode_done)
        {
            /* allow the queue to fill up so that the packets can be sorted properly */
            continue;
        }
        
        if (!removePacket(streamLace, &packet))
        {
            if (decode_done)
            {
                /* the queue is empty, we are done */
                break;
            }
            
            assert(decode_done);
            continue;
        }
        
        packetStartTime = 
            (double)(packet.pts) * 
            (double)(ic->streams[packet.stream_index]->time_base.num) /
            (double)(ic->streams[packet.stream_index]->time_base.den);
        
        packetDuration =
            (double)(packet.duration) *
            (double)(ic->streams[packet.stream_index]->time_base.num) /
            (double)(ic->streams[packet.stream_index]->time_base.den);
        
#if !defined(NDEBUG) && (defined(DEBUG) || defined(_DEBUG))
        if (av_log_get_level() >= AV_LOG_VERBOSE)
            fprintf(stderr,
                    "stream %i, packet [%f, %f)\n",
                    packet.stream_index,
                    packetStartTime,
                    packetStartTime + packetDuration);
#endif

        segment_duration = packetStartTime + packetDuration - prev_segment_time;

        // NOTE: segments are supposed to start on a keyframe.
        // If the keyframe interval and segment duration do not match
        // forcing the segment creation for "better seeking behavior"
        // will result in decoding artifacts after seeking or stream switching.
        if (packet.stream_index == video_index && (packet.flags & AV_PKT_FLAG_KEY || strict_segment_duration)) {
            segment_time = packetStartTime;
        }
        else if (video_index < 0) {
            segment_time = packetStartTime;
        }
        else {
            segment_time = prev_segment_time;
        }

        if (segment_time - prev_segment_time + segment_duration_error_tolerance >
            target_segment_duration + extra_duration_needed) 
        {
            avio_flush(oc->pb);
            avio_close(oc->pb);

            // Keep track of accumulated rounding error to account for it in later chunks.
            double segment_duration = segment_time - prev_segment_time;
            int rounded_segment_duration = (int)(segment_duration + 0.5);
            extra_duration_needed += (double)rounded_segment_duration - segment_duration;

            updatePlaylist(playlist,
                           playlist_filename,
                           output_filename,
                           output_index,
                           rounded_segment_duration);
            
            snprintf(output_filename, strlen(output_prefix) + 15, "%s-%u.ts", output_prefix, ++output_index);
            if (avio_open(&oc->pb, output_filename, AVIO_FLAG_WRITE) < 0) {
                fprintf(stderr, "Could not open '%s'\n", output_filename);
                break;
            }

            // close when we find the 'kill' file
            if (kill_file) {
                FILE* fp = fopen("kill", "rb");
                if (fp) {
                    fprintf(stderr, "user abort: found kill file\n");
                    fclose(fp);
                    remove("kill");
                    decode_done = 1;
                    removeAllPackets(streamLace);
                }
            }
            prev_segment_time = segment_time;
        }

        ret = av_interleaved_write_frame(oc, &packet);
        if (ret < 0) {
            fprintf(stderr, "Warning: Could not write frame of stream\n");
        }
        else if (ret > 0) {
            fprintf(stderr, "End of stream requested\n");
            av_free_packet(&packet);
            break;
        }

        av_free_packet(&packet);
    } while (!decode_done || countPackets(streamLace) > 0);

    av_write_trailer(oc);

    if (video_index >= 0) {
      avcodec_close(video_st->codec);
    }

    for(i = 0; i < oc->nb_streams; i++) {
        av_freep(&oc->streams[i]->codec);
        av_freep(&oc->streams[i]);
    }

    avio_close(oc->pb);
    av_free(oc);

    updatePlaylist(playlist,
                   playlist_filename,
                   output_filename,
                   output_index,
                   segment_duration);
    closePlaylist(playlist);
    releasePlaylist(&playlist);
    
    if (pid_filename)
    {
        remove(pid_filename);
    }

    return 0;

error:
    if (pid_filename)
    {
        remove(pid_filename);
    }

    return 1;

}
예제 #28
0
static void
updateLivePlaylist(TSMPlaylist * playlist,
                   const char * playlistFileName,
                   const char * outputFileName,
                   const unsigned int segmentIndex,
                   const double segmentDuration)
{
    unsigned int bufferIndex = 0;
    TSMSegmentInfo * nextSegment = NULL;
    TSMSegmentInfo removeMe;
    memset(&removeMe, 0, sizeof(removeMe));
    assert(!playlist->file);
    
    if (playlist->count == playlist->bufferCapacity)
    {
        /* keep track of the segment that should be removed */
        removeMe = playlist->buffer[playlist->first];
        
        /* make room for the new segment */
        playlist->first++;
        playlist->first %= playlist->bufferCapacity;
    }
    else
    {
        playlist->count++;
    }

    /* store the new segment info */
    bufferIndex = ((playlist->first + playlist->count - 1) %
                   playlist->bufferCapacity);
    nextSegment = &playlist->buffer[bufferIndex];
    nextSegment->filename = duplicateString(outputFileName);
    nextSegment->duration = segmentDuration;
    nextSegment->index = segmentIndex;
    
    /* live streaming -- write full playlist from scratch */
    playlist->file = fopen_utf8(playlistFileName, "w+b");
    
    if (playlist->file)
    {
        const TSMSegmentInfo * first = &playlist->buffer[playlist->first];
        
        char tmp[1024] = { 0 };
        snprintf(tmp,
                 sizeof(tmp),
                 "#EXTM3U\n"
                 "#EXT-X-TARGETDURATION:%u\n"
                 "#EXT-X-MEDIA-SEQUENCE:%u\n",
                 playlist->targetDuration,
                 first->index);
        fwrite(tmp, strlen(tmp), 1, playlist->file);
        
        for (unsigned int i = 0; i < playlist->count; i++)
        {
            unsigned int j = ((playlist->first + i) %
                              playlist->bufferCapacity);
            
            const TSMSegmentInfo * segment = &playlist->buffer[j];
            snprintf(tmp,
                     sizeof(tmp),
                     "#EXTINF:%u,\n%s%s\n",
                     (int)(segment->duration + 0.5),
                     playlist->httpPrefix,
                     segment->filename);
            fwrite(tmp, strlen(tmp), 1, playlist->file);
        }
        
        // snprintf(tmp, sizeof(tmp), "#EXT-X-ENDLIST\n");
        // fwrite(tmp, strlen(tmp), 1, playlist->file);
        
        fclose(playlist->file);
        playlist->file = NULL;
    }
    else
    {
        fprintf(stderr,
                "Could not open m3u8 index file (%s), "
                "no index file will be created\n",
                playlistFileName);
    }
    
    if (removeMe.filename)
    {
        /* remove the oldest segment file */
        remove(removeMe.filename);
        free(removeMe.filename);
    }
}
예제 #29
0
파일: emu.cpp 프로젝트: Vogtinator/CEmu
bool emu_start() {
    bool ret = false;
    long lSize;

    asic_init();

    if (rom_image == NULL) {
        gui_console_printf("No ROM image specified.");
    }
    else {
        FILE *rom = fopen_utf8(rom_image, "rb");
        do {
            if (rom) {
                uint16_t field_type;
                const uint8_t *outer;
                const uint8_t *current;
                const uint8_t *data;
                uint32_t outer_field_size;
                uint32_t data_field_size;
                ti_device_type device_type;
                uint32_t offset;

                // Get ROM file size
                if (fseek(rom, 0L, SEEK_END) < 0) {
                    break;
                }

                lSize = ftell(rom);
                if (lSize < 0) {
                    break;
                }

                if (fseek(rom, 0L, SEEK_SET) < 0) {
                    break;
                }

                // Read whole ROM.
                if (fread(asic.mem->flash.block, 1, lSize, rom) < (size_t)lSize) {
                    break;
                }

                // Parse certificate fields to determine model.
                //device_type = (ti_device_type)(asic.mem->flash.block[0x20017]);
                // We've heard of the OS base being at 0x30000 on at least one calculator.
                for (offset = 0x20000U; offset < 0x40000U; offset += 0x10000U) {
                    outer = asic.mem->flash.block;
                    // Outer 0x800(0) field.
                    if (cert_field_get(outer + offset, asic.mem->flash.size - offset, &field_type, &outer, &outer_field_size)) {
                        break;
                    }
                    if (field_type != 0x800F /*|| field_type == 0x800D || field_type == 0x800E*/) {
                        continue;
                    }
                    //fprintf(stderr, "outer: %p\t%04X\t%p\t%u\n", asic.mem->flash.block, field_type, outer, outer_field_size);

                    // Inner 0x801(0) field: calculator model
                    if (cert_field_get(outer, outer_field_size, &field_type, &data, &data_field_size)) {
                        break;
                    }
                    //fprintf(stderr, "inner 1: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);
                    if (field_type != 0x8012 || data[0] != 0x13) {
                        break;
                    }

                    // Inner 0x802(0) field: skip.
                    data_field_size = outer_field_size - (data + data_field_size - outer);
                    data = outer;
                    if (cert_field_next(&data, &data_field_size)) {
                        break;
                    }
                    //fprintf(stderr, "data: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);
                    current = data;
                    if (cert_field_get(current, data_field_size, &field_type, &data, &data_field_size)) {
                        break;
                    }
                    //fprintf(stderr, "inner 2: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);
                    if (field_type != 0x8021) {
                        break;
                    }

                    // Inner 0x803(0) field: skip.
                    data_field_size = outer_field_size - (data + data_field_size - outer);
                    data = current;
                    if (cert_field_next(&data, &data_field_size)) {
                        break;
                    }
                    current = data;
                    //fprintf(stderr, "data: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);
                    if (cert_field_get(current, data_field_size, &field_type, &data, &data_field_size)) {
                        break;
                    }
                    //fprintf(stderr, "inner 3: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);
                    if (field_type != 0x8032) {
                        break;
                    }

                    // Inner 0x80A(0) field: skip.
                    data_field_size = outer_field_size - (data + data_field_size - outer);
                    data = current;
                    if (cert_field_next(&data, &data_field_size)) {
                        break;
                    }
                    current = data;
                    //fprintf(stderr, "data: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);
                    if (cert_field_get(current, data_field_size, &field_type, &data, &data_field_size)) {
                        break;
                    }
                    //fprintf(stderr, "inner 4: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);
                    if (field_type != 0x80A1) {
                        break;
                    }

                    // Inner 0x80C(0) field: keep.
                    data_field_size = outer_field_size - (data + data_field_size - outer);
                    data = current;
                    if (cert_field_next(&data, &data_field_size)) {
                        break;
                    }
                    current = data;
                    //fprintf(stderr, "data: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);
                    if (cert_field_get(current, data_field_size, &field_type, &data, &data_field_size)) {
                        break;
                    }
                    //fprintf(stderr, "inner 5: %p\t%04X\t%p\t%u\n", outer, field_type, data, data_field_size);
                    if (field_type != 0x80C2) {
                        break;
                    }

                    //fprintf(stderr, "Found calculator type %02X\n", data[1]);
                    if (data[1] != 0 && data[1] != 1) {
                        break;
                    }
                    device_type = (ti_device_type)(data[1]);

                    // If we come here, we've found something.
                    ret = true;
                    break;
                }


                if (ret) {
                    control.device_type = device_type;
                    asic.device_type = device_type;
                }

            }
        } while(0);

        if (!ret) {
            gui_console_printf("Error opening ROM image.\n", rom_image);
            emu_cleanup();
        }

        if (rom) {
            fclose(rom);
        }
    }

    return ret;
}
예제 #30
0
// ****************************************************************************
// * LoadGIF                                                                  *
// *   Load a GIF File into the CAnimatedGifSet object                             *
// *                        (c) Nov 2000, Juan Soulie <*****@*****.**> *
// ****************************************************************************
int CAnimatedGifSet::LoadGIF (const char * szFileName)
{
  int n;
  // Global GIF variables:
  int GlobalBPP;       // Bits per Pixel.
  COLOR * GlobalColorMap;     // Global colormap (allocate)

  struct GIFGCEtag
  {                // GRAPHIC CONTROL EXTENSION
    unsigned char BlockSize;   // Block Size: 4 bytes
    unsigned char PackedFields;  // 3.. Packed Fields. Bits detail:
    //    0: Transparent Color Flag
    //    1: User Input Flag
    //  2-4: Disposal Method
    unsigned short Delay;     // 4..5 Delay Time (1/100 seconds)
    unsigned char Transparent;  // 6.. Transparent Color Index
  }
  gifgce;

  struct GIFNetscapeTag
  {
    unsigned char comment[11];  //4...14  NETSCAPE2.0
    unsigned char SubBlockLength; //15      0x3
    unsigned char reserved;       //16      0x1
    unsigned short iIterations ;    //17..18  number of iterations (lo-hi)
  }
  gifnetscape;

  int GraphicExtensionFound = 0;

  // OPEN FILE
  FILE *fd = fopen_utf8(CSpecialProtocol::TranslatePath(szFileName), "rb");
  if (!fd)
  {
    return 0;
  }

  // *1* READ HEADERBLOCK (6bytes) (SIGNATURE + VERSION)
  char szSignature[6];    // First 6 bytes (GIF87a or GIF89a)
  int iRead = fread(szSignature, 1, 6, fd);
  if (iRead != 6)
  {
    fclose(fd);
    return 0;
  }
  if ( memcmp(szSignature, "GIF", 2) != 0)
  {
    fclose(fd);
    return 0;
  }
  // *2* READ LOGICAL SCREEN DESCRIPTOR
  struct GIFLSDtag
  {
    unsigned short ScreenWidth;  // Logical Screen Width
    unsigned short ScreenHeight; // Logical Screen Height
    unsigned char PackedFields;  // Packed Fields. Bits detail:
    //  0-2: Size of Global Color Table
    //    3: Sort Flag
    //  4-6: Color Resolution
    //    7: Global Color Table Flag
    unsigned char Background;  // Background Color Index
    unsigned char PixelAspectRatio; // Pixel Aspect Ratio
  }
  giflsd;

  iRead = fread(&giflsd, 1, sizeof(giflsd), fd);
  if (iRead != sizeof(giflsd))
  {
    fclose(fd);
    return 0;
  }
  // endian swap
  SWAP16(giflsd.ScreenWidth);
  SWAP16(giflsd.ScreenHeight);

  GlobalBPP = (giflsd.PackedFields & 0x07) + 1;

  // fill some animation data:
  FrameWidth = giflsd.ScreenWidth;
  FrameHeight = giflsd.ScreenHeight;
  nLoops = 1; //default=play animation 1 time

  // *3* READ/GENERATE GLOBAL COLOR MAP
  GlobalColorMap = new COLOR [1 << GlobalBPP];
  if (giflsd.PackedFields & 0x80) // File has global color map?
    for (n = 0;n < 1 << GlobalBPP;n++)
    {
      GlobalColorMap[n].r = getbyte(fd);
      GlobalColorMap[n].g = getbyte(fd);
      GlobalColorMap[n].b = getbyte(fd);
      GlobalColorMap[n].x = 0;
    }

  else // GIF standard says to provide an internal default Palette:
    for (n = 0;n < 256;n++)
    {
      GlobalColorMap[n].r = GlobalColorMap[n].g = GlobalColorMap[n].b = n;
      GlobalColorMap[n].x = 0;
    }

  // *4* NOW WE HAVE 3 POSSIBILITIES:
  //  4a) Get and Extension Block (Blocks with additional information)
  //  4b) Get an Image Separator (Introductor to an image)
  //  4c) Get the trailer Char (End of GIF File)
  do
  {
    int charGot = getbyte(fd);

    if (charGot == 0x21)  // *A* EXTENSION BLOCK
    {
      unsigned char extensionType = getbyte(fd);
      switch (extensionType)
      {
      case 0xF9:    // Graphic Control Extension
        {
          if (fread((char*)&gifgce, 1, sizeof(gifgce), fd) == sizeof(gifgce))
            SWAP16(gifgce.Delay);
          GraphicExtensionFound++;
          getbyte(fd); // Block Terminator (always 0)
        }
        break;

      case 0xFE:    // Comment Extension: Ignored
        {
          while (int nBlockLength = getbyte(fd))
            for (n = 0;n < nBlockLength;n++) getbyte(fd);
        }
        break;

      case 0x01:    // PlainText Extension: Ignored
        {
          while (int nBlockLength = getbyte(fd))
            for (n = 0;n < nBlockLength;n++) getbyte(fd);
        }
        break;

      case 0xFF:    // Application Extension: Ignored
        {
          int nBlockLength = getbyte(fd);
          if (nBlockLength == 0x0b)
          {
            struct GIFNetscapeTag tag;
            if (fread((char*)&tag, 1, sizeof(gifnetscape), fd) == sizeof(gifnetscape))
            {
              SWAP16(tag.iIterations);
              nLoops = tag.iIterations;
            }
            else
              nLoops = 0;

            if (nLoops) nLoops++;
            getbyte(fd);
          }
          else
          {
            do
            {
              for (n = 0;n < nBlockLength;n++) getbyte(fd);
            }
            while ((nBlockLength = getbyte(fd)) != 0);
          }
        }
        break;

       default:    // Unknown Extension: Ignored
        {
          // read (and ignore) data sub-blocks
          while (int nBlockLength = getbyte(fd))
            for (n = 0;n < nBlockLength;n++) getbyte(fd);
        }
        break;
      }
    }
    else if (charGot == 0x2c)
    { // *B* IMAGE (0x2c Image Separator)
      // Create a new Image Object:
      CAnimatedGif* NextImage = new CAnimatedGif();

      // Read Image Descriptor
      struct GIFIDtag
      {
        unsigned short xPos;     // Image Left Position
        unsigned short yPos;     // Image Top Position
        unsigned short Width;     // Image Width
        unsigned short Height;    // Image Height
        unsigned char PackedFields;  // Packed Fields. Bits detail:
        //  0-2: Size of Local Color Table
        //  3-4: (Reserved)
        //    5: Sort Flag
        //    6: Interlace Flag
        //    7: Local Color Table Flag
      }
      gifid;

      memset(&gifid, 0, sizeof(gifid));

      int LocalColorMap = 0;
      if (fread((char*)&gifid, 1, sizeof(gifid), fd) == sizeof(gifid))
      {
        SWAP16(gifid.xPos);
        SWAP16(gifid.yPos);
        SWAP16(gifid.Width);
        SWAP16(gifid.Height);

        LocalColorMap = (gifid.PackedFields & 0x08) ? 1 : 0;
      }

      NextImage->Init(gifid.Width, gifid.Height, LocalColorMap ? (gifid.PackedFields&7) + 1 : GlobalBPP);

      // Fill NextImage Data
      NextImage->xPos = gifid.xPos;
      NextImage->yPos = gifid.yPos;
      if (GraphicExtensionFound)
      {
        NextImage->Transparent = (gifgce.PackedFields & 0x01) ? gifgce.Transparent : -1;
        NextImage->Transparency = (gifgce.PackedFields & 0x1c) > 1 ? 1 : 0;
        NextImage->Delay = gifgce.Delay * 10;
      }

      if (NextImage->Transparent != -1)
        memset(NextImage->Raster, NextImage->Transparent, NextImage->BytesPerRow * NextImage->Height);
      else
        memset(NextImage->Raster, giflsd.Background, NextImage->BytesPerRow * NextImage->Height);

      // Read Color Map (if descriptor says so)
      size_t palSize = sizeof(COLOR)*(1 << NextImage->BPP);
      bool isPalRead = false;
      if (LocalColorMap && fread((char*)NextImage->Palette, 1, palSize, fd) == palSize)
        isPalRead = true;

      // Copy global, if no palette
      if (!isPalRead)
        memcpy(NextImage->Palette, GlobalColorMap, palSize);

      short firstbyte = getbyte(fd); // 1st byte of img block (CodeSize)

      // Calculate compressed image block size
      // to fix: this allocates an extra byte per block
      long ImgStart, ImgEnd;
      ImgEnd = ImgStart = ftell(fd);
      while ((n = getbyte(fd)) !=  0) fseek (fd, ImgEnd += n + 1, SEEK_SET );
      fseek (fd, ImgStart, SEEK_SET);

      // Allocate Space for Compressed Image
      char * pCompressedImage = new char [ImgEnd - ImgStart + 4];

      // Read and store Compressed Image
      char * pTemp = pCompressedImage;
      while (int nBlockLength = getbyte(fd))
      {
        if (fread(pTemp, 1, nBlockLength, fd) != (size_t)nBlockLength)
        {
        // Error?
        }
        pTemp += nBlockLength;
      }

      // Call LZW/GIF decompressor
      n = LZWDecoder(
            (char*) pCompressedImage,
            (char*) NextImage->Raster,
            firstbyte, NextImage->BytesPerRow, //NextImage->AlignedWidth,
            gifid.Width, gifid.Height,
            ((gifid.PackedFields & 0x40) ? 1 : 0) //Interlaced?
          );

      if (n)
        AddImage(NextImage);
      else
      {
        delete NextImage;
        ERRORMSG("GIF File Corrupt");
      }

      // Some cleanup
      delete[] pCompressedImage;
      GraphicExtensionFound = 0;
    }
    else if (charGot == 0x3b)
    {
      // *C* TRAILER: End of GIF Info
      break; // Ok. Standard End.
    }

  }
  while ( !feof(fd) );

  delete[] GlobalColorMap;
  fclose(fd);
  if ( GetImageCount() == 0) ERRORMSG("Premature End Of File");
  return GetImageCount();
}