示例#1
0
int
ppf_set_fid (const char *ppf, const char *fidname)
{
    int fidsize, ppfsize, pos;
    char ppfname[FILENAME_MAX],
         fidbuf[MAX_ID_SIZE + 34 + 1] = "@BEGIN_FILE_ID.DIZ"; // +1 for string terminator

    strcpy (ppfname, ppf);
    ucon64_file_handler (ppfname, NULL, 0);
    fcopy (ppf, 0, fsizeof (ppf), ppfname, "wb"); // no copy if one file

    printf ("Adding FILE_ID.DIZ (%s)...\n", fidname);
    fidsize = ucon64_fread (fidbuf + 18, 0, MAX_ID_SIZE, fidname);
    memcpy (fidbuf + 18 + fidsize, "@END_FILE_ID.DIZ", 16);

    ppfsize = fsizeof (ppfname);
    pos = ucon64_find (ppfname, 0, ppfsize, "@BEGIN_FILE_ID.DIZ", 18,
                       MEMCMP2_CASE | UCON64_FIND_QUIET);
    if (pos == -1)
        pos = ppfsize;
    truncate (ppfname, pos);

    ucon64_fwrite (fidbuf, pos, fidsize + 18 + 16, ppfname, "r+b");
    pos += fidsize + 18 + 16;
#ifdef  WORDS_BIGENDIAN
    fidsize = bswap_32 (fidsize);                 // Write file size in little-endian format
#endif
    ucon64_fwrite (&fidsize, pos, 4, ppfname, "r+b");

    printf (ucon64_msg[WROTE], ppfname);
    return 0;
}
示例#2
0
static int
scramble (const char *src, char *dst)
{
  unsigned char *ptr = NULL;
  uint32_t sz = 0;
  FILE *fh;

  if (!(fh = fopen (src, "rb")))
    return -1;

  sz = fsizeof (src);

  if (!(ptr = (unsigned char *) malloc (sz)))
    return -1;

  if (fread (ptr, 1, sz, fh) != sz)
    return -1;

  fclose (fh);

  if (!(fh == fopen (dst, "wb")))
    return -1;
  save_file (fh, ptr, sz);

  fclose (fh);

  free (ptr);
  return 0;
}
示例#3
0
int
truncate2 (const char *filename, off_t new_size)
{
  int size = fsizeof (filename);
  struct stat fstate;

  stat (filename, &fstate);
  if (chmod (filename, fstate.st_mode | S_IWUSR))
    return -1;

  if (size < new_size)
    {
      FILE *file;
      unsigned char padbuffer[MAXBUFSIZE];
      int n_bytes;

      if ((file = fopen (filename, "ab")) == NULL)
        return -1;

      memset (padbuffer, 0, MAXBUFSIZE);

      while (size < new_size)
        {
          n_bytes = new_size - size > MAXBUFSIZE ? MAXBUFSIZE : new_size - size;
          fwrite (padbuffer, 1, n_bytes, file);
          size += n_bytes;
        }

      fclose (file);
    }
  else
    truncate (filename, new_size);

  return 0;                                     // success
}
示例#4
0
char *
mkbak (const char *filename, backup_t type)
{
  static char buf[FILENAME_MAX];

  if (access (filename, R_OK) != 0)
    return (char *) filename;

  strcpy (buf, filename);
  set_suffix (buf, ".bak");
  if (strcmp (filename, buf) != 0)
    {
      remove (buf);                             // *try* to remove or rename() will fail
      if (rename (filename, buf))               // keep file attributes like date, etc.
        {
          fprintf (stderr, "ERROR: Can't rename \"%s\" to \"%s\"\n", filename, buf);
          exit (1);
        }
    }
  else // handle the case where filename has the suffix ".bak".
    {
      char buf2[FILENAME_MAX];

      if (!dirname2 (filename, buf))
        {
          fprintf (stderr, "INTERNAL ERROR: dirname2() returned NULL\n");
          exit (1);
        }
      if (buf[0] != 0)
        if (buf[strlen (buf) - 1] != FILE_SEPARATOR)
          strcat (buf, FILE_SEPARATOR_S);

      strcat (buf, basename2 (tmpnam2 (buf2)));
      if (rename (filename, buf))
        {
          fprintf (stderr, "ERROR: Can't rename \"%s\" to \"%s\"\n", filename, buf);
          exit (1);
        }
    }

  switch (type)
    {
    case BAK_MOVE:
      return buf;

    case BAK_DUPE:
    default:
      if (fcopy (buf, 0, fsizeof (buf), filename, "wb"))
        {
          fprintf (stderr, "ERROR: Can't open \"%s\" for writing\n", filename);
          exit (1);
        }
      sync ();
      return buf;
    }
}
示例#5
0
int
smd_write_rom (const char *filename, unsigned int parport)
{
  FILE *file;
  unsigned char *buffer;
  int bytesread, bytessend, blocksdone = 0, fsize;
  time_t starttime;

  ffe_init_io (parport);

  if ((file = fopen (filename, "rb")) == NULL)
    {
      fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
      exit (1);
    }
  if ((buffer = (unsigned char *) malloc (BUFFERSIZE)) == NULL)
    {
      fprintf (stderr, ucon64_msg[FILE_BUFFER_ERROR], BUFFERSIZE);
      exit (1);
    }

  fsize = fsizeof (filename);
  printf ("Send: %d Bytes (%.4f Mb)\n", fsize, (float) fsize / MBIT);

  fread (buffer, 1, SMD_HEADER_LEN, file);
  ffe_send_block (0xdc00, buffer, SMD_HEADER_LEN); // send header
  bytessend = SMD_HEADER_LEN;

  ffe_send_command0 (0x2001, 0);

  printf ("Press q to abort\n\n");

  starttime = time (NULL);
  while ((bytesread = fread (buffer, 1, BUFFERSIZE, file)))
    {
      ffe_send_command (5, (unsigned short) blocksdone, 0);
      ffe_send_block (0x8000, buffer, bytesread);
      blocksdone++;

      bytessend += bytesread;
      ucon64_gauge (starttime, bytessend, fsize);
      ffe_checkabort (2);
    }

  // ROM dump > 128 16 KB blocks? (=16 Mb (=2 MB))
  ffe_send_command0 (0x2001, (unsigned char) (blocksdone > 0x80 ? 7 : 3));

  free (buffer);
  fclose (file);
  ffe_deinit_io ();

  return 0;
}
示例#6
0
int
ppf_set_desc (const char *ppf, const char *description)
{
    char desc[50], ppfname[FILENAME_MAX];

    strcpy (ppfname, ppf);
    memset (desc, ' ', 50);
    strncpy (desc, description, strlen (description));
    ucon64_file_handler (ppfname, NULL, 0);
    fcopy (ppf, 0, fsizeof (ppf), ppfname, "wb"); // no copy if one file
    ucon64_fwrite (desc, 6, 50, ppfname, "r+b");

    printf (ucon64_msg[WROTE], ppfname);
    return 0;
}
示例#7
0
int
smd_write_sram (const char *filename, unsigned int parport)
{
  FILE *file;
  unsigned char *buffer;
  int bytesread, bytessend = 0, size;
  unsigned short address;
  time_t starttime;

  ffe_init_io (parport);

  if ((file = fopen (filename, "rb")) == NULL)
    {
      fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
      exit (1);
    }
  if ((buffer = (unsigned char *) malloc (BUFFERSIZE)) == NULL)
    {
      fprintf (stderr, ucon64_msg[FILE_BUFFER_ERROR], BUFFERSIZE);
      exit (1);
    }

  size = fsizeof (filename) - SMD_HEADER_LEN;
  printf ("Send: %d Bytes\n", size);
  fseek (file, SMD_HEADER_LEN, SEEK_SET);       // skip the header

  ffe_send_command0 (0x2001, 4);

  printf ("Press q to abort\n\n");

  address = 0x4000;
  starttime = time (NULL);
  while ((bytesread = fread (buffer, 1, BUFFERSIZE, file)))
    {
      ffe_send_block (address, buffer, bytesread);
      address += 0x4000;

      bytessend += bytesread;
      ucon64_gauge (starttime, bytessend, size);
      ffe_checkabort (2);
    }

  free (buffer);
  fclose (file);
  ffe_deinit_io ();

  return 0;
}
示例#8
0
int
smsgg_write_sram (const char *filename, unsigned int parport, int start_bank)
{
  FILE *file;
  unsigned char buffer[0x4000];
  int size, bytesread, bytessend = 0, address;
  time_t starttime;
  void (*write_block) (int *, unsigned char *) = write_ram_by_byte; // write_ram_by_page
  (void) write_ram_by_page;

  size = fsizeof (filename);
  if (start_bank == -1)
    address = 0;
  else
    {
      if (start_bank < 1 || start_bank > 4)
        {
          fputs ("ERROR: Bank must be a value 1 - 4\n", stderr);
          exit (1);
        }
      address = (start_bank - 1) * 32 * 1024;
    }

  if ((file = fopen (filename, "rb")) == NULL)
    {
      fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
      exit (1);
    }

  ttt_init_io (parport);
  printf ("Send: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);

  starttime = time (NULL);
  while ((bytesread = fread (buffer, 1, 0x4000, file)))
    {
      write_block (&address, buffer);
      bytessend += bytesread;
      ucon64_gauge (starttime, bytessend, size);
    }

  fclose (file);
  ttt_deinit_io ();

  return 0;
}
示例#9
0
int
smsgg_write_rom (const char *filename, unsigned int parport)
{
  FILE *file;
  unsigned char buffer[0x4000];
  int size, address = 0, bytesread, bytessend = 0;
  time_t starttime;
  void (*write_block) (int *, unsigned char *) = write_rom_by_page; // write_rom_by_byte
  (void) write_rom_by_byte;

  if ((file = fopen (filename, "rb")) == NULL)
    {
      fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
      exit (1);
    }
  ttt_init_io (parport);

  size = fsizeof (filename);
  printf ("Send: %d Bytes (%.4f Mb)\n\n", size, (float) size / MBIT);

  eep_reset ();
  if (ttt_get_id () != 0xb0d0)
    {
      fputs ("ERROR: SMS-PRO/GG-PRO flash card (programmer) not detected\n", stderr);
      fclose (file);
      ttt_deinit_io ();
      exit (1);
    }

  starttime = time (NULL);
  eep_reset ();
  while ((bytesread = fread (buffer, 1, 0x4000, file)))
    {
      if ((address & 0xffff) == 0)
        ttt_erase_block (address);
      write_block (&address, buffer);
      bytessend += bytesread;
      ucon64_gauge (starttime, bytessend, size);
    }

  fclose (file);
  ttt_deinit_io ();

  return 0;
}
示例#10
0
// based on sourcecode of MakePPF v2.0 Linux/Unix by Icarus/Paradox
int
ppf_create (const char *orgname, const char *modname)
{
    FILE *orgfile, *modfile, *ppffile;
    char ppfname[FILENAME_MAX], buffer[MAX_ID_SIZE], obuf[512], mbuf[512];
#if 0
    char *fidname = "FILE_ID.DIZ";
#endif
    int x, osize, msize, blocksize, n_changes, total_changes = 0;
    unsigned int seekpos = 0, pos;

    osize = fsizeof (orgname);
    msize = fsizeof (modname);
#ifndef DIFF_FSIZE
    if (osize != msize)
    {
        fprintf (stderr, "ERROR: File sizes do not match\n");
        return -1;
    }
#endif

    if ((orgfile = fopen (orgname, "rb")) == NULL)
    {
        fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], orgname);
        exit (1);
    }
    if ((modfile = fopen (modname, "rb")) == NULL)
    {
        fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], modname);
        exit (1);
    }
    strcpy (ppfname, modname);
    set_suffix (ppfname, ".ppf");
    ucon64_file_handler (ppfname, NULL, 0);
    if ((ppffile = fopen (ppfname, "wb")) == NULL)
    {
        fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], ppfname);
        exit (1);
    }

    // creating PPF 2.0 header
    fwrite ("PPF20", 5, 1, ppffile);              // magic
    fputc (1, ppffile);                           // encoding method
    memset (buffer, ' ', 50);
    fwrite (buffer, 50, 1, ppffile);              // description line
#ifdef  WORDS_BIGENDIAN
    x = bswap_32 (osize);
    fwrite (&x, 4, 1, ppffile);
#else
    fwrite (&osize, 4, 1, ppffile);               // orgfile size
#endif
    fseek (orgfile, 0x9320, SEEK_SET);
    memset (buffer, 0, 1024);                     // one little hack that makes PPF
    fread (buffer, 1024, 1, orgfile);             //  suitable for files < 38688 bytes
    fwrite (buffer, 1024, 1, ppffile);            // 1024 byte block

    printf ("Writing patch data, please wait...\n");
    // finding changes
    fseek (orgfile, 0, SEEK_SET);
    fseek (modfile, 0, SEEK_SET);
    while ((blocksize = fread (obuf, 1, 255, orgfile)))
    {
        blocksize = fread (mbuf, 1, blocksize, modfile);
#ifdef  DIFF_FSIZE
        if (blocksize == 0)
            break;
#endif
        pos = seekpos;
        x = 0;
        while (x != blocksize)
        {
            if (obuf[x] != mbuf[x])
            {
                pos = seekpos + x;
                n_changes = 0;
                do
                {
                    buffer[n_changes] = mbuf[x];
                    n_changes++;
                    x++;
                }
                while (x != blocksize && obuf[x] != mbuf[x]);
                total_changes += n_changes;
#ifdef  WORDS_BIGENDIAN
                pos = bswap_32 (pos);
#endif
                fwrite (&pos, 4, 1, ppffile);
                fputc (n_changes, ppffile);
                fwrite (buffer, n_changes, 1, ppffile);
            }
            else
                x++;
        }
        seekpos += blocksize;
    }

#ifdef  DIFF_FSIZE
    if (msize > osize)
    {
        pos = seekpos;
        while ((blocksize = fread (buffer, 1, 255, modfile)))
        {
            total_changes += blocksize;
#ifdef  WORDS_BIGENDIAN
            x = bswap_32 (pos);
            fwrite (&x, 4, 1, ppffile);
#else
            fwrite (&pos, 4, 1, ppffile);
#endif
            fputc (blocksize, ppffile);
            fwrite (buffer, blocksize, 1, ppffile);
            pos += blocksize;
        }
    }
    else if (msize < osize)
        printf ("WARNING: %s is smaller than %s\n"
                "         PPF can't store information about that fact\n",
                modname, orgname);
#endif

    fclose (orgfile);
    fclose (modfile);

    if (total_changes == 0)
    {
        printf ("%s and %s are identical\n"
                "Removing: %s\n", orgname, modname, ppfname);
        fclose (ppffile);
        remove (ppfname);
        return -1;
    }

#if 0
    if (fidname)
    {
        int fsize = fsizeof (fidname);
        if (fsize > MAX_ID_SIZE)
            fsize = MAX_ID_SIZE;                    // File id only up to 3072 bytes!
        printf ("Adding FILE_ID.DIZ (%s)...\n", fidname);
        ucon64_fread (buffer, 0, fsize, fidname);
        fwrite ("@BEGIN_FILE_ID.DIZ", 18, 1, ppffile);
        fwrite (buffer, fsize, 1, ppffile);
        fwrite ("@END_FILE_ID.DIZ", 16, 1, ppffile);
#ifdef  WORDS_BIGENDIAN
        fsize = bswap_32 (fsize);                 // Write file size in little-endian format
#endif
        fwrite (&fsize, 4, 1, ppffile);
    }
#endif
    fclose (ppffile);

    printf (ucon64_msg[WROTE], ppfname);
    return 0;
}
示例#11
0
// based on source code of ApplyPPF v2.0 for Linux/Unix by Icarus/Paradox
int
ppf_apply (const char *mod, const char *ppfname)
{
    FILE *modfile, *ppffile;
    char desc[50 + 1], diz[MAX_ID_SIZE + 1], buffer[1024], ppfblock[1024],
         modname[FILENAME_MAX];
    int x, method, dizlen = 0, modlen, ppfsize, bytes_to_skip = 0, n_changes;
    unsigned int pos;

    strcpy (modname, mod);
    ucon64_file_handler (modname, NULL, 0);
    fcopy (mod, 0, fsizeof (mod), modname, "wb"); // no copy if one file

    if ((modfile = fopen (modname, "r+b")) == NULL)
    {
        fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], modname);
        exit (1);
    }
    if ((ppffile = fopen (ppfname, "rb")) == NULL)
    {
        fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], ppfname);
        exit (1);
    }

    // Is it a PPF File?
    fread (buffer, 3, 1, ppffile);
    if (strncmp ("PPF", buffer, 3))
    {
        fprintf (stderr, "ERROR: %s is not a valid PPF file\n", ppfname);
        exit (1);
    }

    // What encoding method? PPF 1.0 or PPF 2.0?
    fseek (ppffile, 5, SEEK_SET);
    method = fgetc (ppffile);
    if (method != 0 && method != 1)
    {
        fprintf (stderr, "ERROR: Unknown encoding method! Check for updates\n");
        exit (1);
    }

    ppfsize = fsizeof (ppfname);

    // Show PPF information
    fseek (ppffile, 6, SEEK_SET);                 // Read description line
    fread (desc, 50, 1, ppffile);
    desc[50] = 0;                                 // terminate string
    printf ("\n"                                  // print a newline between
            "Filename        : %s\n", ppfname);   //  backup message and PPF info
    printf ("Encoding method : %d (PPF %d.0)\n", method, method + 1);
    printf ("Description     : %s\n", desc);

    if (method == 0)                              // PPF 1.0
    {
        printf ("FILE_ID.DIZ     : No\n\n");
        x = 56;                                   // file pointer is at right position (56)
    }
    else // method == 1                           // PPF 2.0
    {
        fseek (ppffile, ppfsize - 8, SEEK_SET);
        fread (buffer, 4, 1, ppffile);

        // Is there a file id?
        if (strncmp (".DIZ", buffer, 4))
            printf ("FILE_ID.DIZ     : No\n\n");
        else
        {
            printf ("FILE_ID.DIZ     : Yes, showing...\n");
            fread (&dizlen, 4, 1, ppffile);
#ifdef  WORDS_BIGENDIAN
            dizlen = bswap_32 (dizlen);           // FILE_ID.DIZ size is in little-endian format
#endif
            fseek (ppffile, ppfsize - dizlen - (16 + 4), SEEK_SET);
            bytes_to_skip = dizlen + 18 + 16 + 4; // +4 for FILE_ID.DIZ size integer
            if (dizlen > MAX_ID_SIZE)
                dizlen = MAX_ID_SIZE;               // do this after setting bytes_to_skip!
            fread (diz, dizlen, 1, ppffile);
            diz[dizlen] = 0;                      // terminate string
            puts (diz);
        }

        // Do the file size check
        fseek (ppffile, 56, SEEK_SET);
        fread (&x, 4, 1, ppffile);
#ifdef  WORDS_BIGENDIAN
        x = bswap_32 (x);                         // file size is stored in little-endian format
#endif
        modlen = fsizeof (modname);
        if (x != modlen)
        {
            fprintf (stderr, "ERROR: The size of %s is not %d bytes\n", modname, x);
            exit (1);
        }

        // Do the binary block check
        fseek (ppffile, 60, SEEK_SET);
        fread (ppfblock, 1024, 1, ppffile);
        fseek (modfile, 0x9320, SEEK_SET);
        memset (buffer, 0, 1024);                 // one little hack that makes PPF
        fread (buffer, 1024, 1, modfile);         //  suitable for files < 38688 bytes
        if (memcmp (ppfblock, buffer, 1024))
        {
            fprintf (stderr, "ERROR: This patch does not belong to this image\n");
            exit (1);
        }

        fseek (ppffile, 1084, SEEK_SET);
        x = 1084;
    }

    // Patch the image
    printf ("Patching...\n");
    for (; x < ppfsize - bytes_to_skip; x += 4 + 1 + n_changes)
    {
        fread (&pos, 4, 1, ppffile);              // Get position for modfile
#ifdef  WORDS_BIGENDIAN
        pos = bswap_32 (pos);
#endif
        n_changes = fgetc (ppffile);              // How many bytes do we have to write?
        fread (buffer, n_changes, 1, ppffile);    // And this is what we have to write
        fseek (modfile, pos, SEEK_SET);           // Go to the right position in the modfile
        fwrite (buffer, n_changes, 1, modfile);   // Write n_changes bytes to that pos
    }

    printf ("Done\n");
    fclose (ppffile);
    fclose (modfile);

    printf (ucon64_msg[WROTE], modname);
    return 0;
}
示例#12
0
文件: bsl.c 项目: Godzil/quickdev16
int
bsl_apply (const char *mod, const char *bslname)
{
  FILE *modfile, *bslfile;
  unsigned char byte;
  char buf[4096], modname[FILENAME_MAX];
  int data, nbytes, offset;

  strcpy (modname, mod);
  ucon64_file_handler (modname, NULL, 0);
  fcopy (mod, 0, fsizeof (mod), modname, "wb"); // no copy if one file

  if ((modfile = fopen (modname, "r+b")) == NULL)
    {
      fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], modname);
      return -1;
    }
  if ((bslfile = fopen (bslname, "rb")) == NULL)
    {
      fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], bslname);
      return -1;
    }

  printf ("Applying BSL/Baseline patch...\n");

  while (!feof (bslfile))                       // we could use 1, but feof() makes it fail-safe
    {
      fscanf (bslfile, "%d\n", &offset);
      fscanf (bslfile, "%d\n", &data);
      if ((offset == -1) && (data == -1))
        break;

      fseek (modfile, offset, SEEK_SET);
      fputc (data, modfile);
    }

  fscanf (bslfile, "%d\n", &offset);
  fscanf (bslfile, "%d\n", &nbytes);
  fseek (modfile, offset, SEEK_SET);
  if (nbytes > 0)
    {
      while (nbytes > 4096)
        {
          fread (buf, 4096, 1, bslfile);
          fwrite (buf, 4096, 1, modfile);
          nbytes -= 4096;
        }
      while (nbytes-- >= 0)                     // yes, one byte more than the
        {                                       //  _value_ read from the BSL file
          byte = (unsigned char) fgetc (bslfile);
          fputc (byte, modfile);
        }
    }

  printf ("Patching complete\n\n");
  printf (ucon64_msg[WROTE], modname);
  printf ("\n"
          "NOTE: Sometimes you have to add/strip a 512 bytes header when you patch a ROM\n"
          "      This means you must modify for example a SNES ROM with -swc or -stp or\n"
          "      the patch will not work\n");

  fclose (bslfile);
  fclose (modfile);

  return 0;
}
示例#13
0
文件: pce.c 项目: Godzil/quickdev16
int
pce_multi (int truncate_size, char *fname)
{
#define BUFSIZE (32 * 1024)
  int n, n_files, file_no, bytestowrite, byteswritten, done, truncated = 0,
      totalsize = 0, size, org_do_not_calc_crc = ucon64.do_not_calc_crc;
  struct stat fstate;
  FILE *srcfile, *destfile;
  char destname[FILENAME_MAX];
  unsigned char buffer[BUFSIZE];

  if (truncate_size == 0)
    {
      fprintf (stderr, "ERROR: Cannot make multi-game file of 0 bytes\n");
      return -1;
    }

  if (fname != NULL)
    {
      strcpy (destname, fname);
      n_files = ucon64.argc;
    }
  else
    {
      strcpy (destname, ucon64.argv[ucon64.argc - 1]);
      n_files = ucon64.argc - 1;
    }

  ucon64_file_handler (destname, NULL, OF_FORCE_BASENAME);
  if ((destfile = fopen (destname, "wb")) == NULL)
    {
      fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], destname);
      return -1;
    }

  printf ("Creating multi-game file for PCE-PRO: %s\n", destname);

  file_no = 0;
  for (n = 1; n < n_files; n++)
    {
      if (access (ucon64.argv[n], F_OK))
        continue;                               // "file" does not exist (option)
      stat (ucon64.argv[n], &fstate);
      if (!S_ISREG (fstate.st_mode))
        continue;
      if (file_no == 32)                        // loader + 31 games
        {
          printf ("WARNING: A multi-game file can contain a maximum of 31 games. The other files\n"
                  "         are ignored.\n");
          break;
        }

      ucon64.console = UCON64_UNKNOWN;
      ucon64.fname = ucon64.argv[n];
      ucon64.file_size = fsizeof (ucon64.fname);
      // DON'T use fstate.st_size, because file could be compressed
      ucon64.do_not_calc_crc = 1;
      if (pce_init (ucon64.nfo) != 0)
        printf ("WARNING: %s does not appear to be a PC-Engine ROM\n", ucon64.fname);

      if ((srcfile = fopen (ucon64.fname, "rb")) == NULL)
        {
          fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], ucon64.fname);
          continue;
        }
      if (ucon64.nfo->backup_header_len)
        fseek (srcfile, ucon64.nfo->backup_header_len, SEEK_SET);
      size = ucon64.file_size - ucon64.nfo->backup_header_len;

      if (file_no == 0)
        {
          printf ("Loader: %s\n", ucon64.fname);
          if (size != PCE_PRO_LOADER_SIZE)
            printf ("WARNING: Are you sure %s is a loader binary?\n", ucon64.fname);
        }
      else
        {
          printf ("ROM%d: %s\n", file_no, ucon64.fname);
          write_game_table_entry (destfile, file_no, totalsize, size);
        }
      file_no++;

      done = 0;
      byteswritten = 0;                         // # of bytes written per file
      while (!done)
        {
          bytestowrite = fread (buffer, 1, BUFSIZE, srcfile);
          if (totalsize + bytestowrite > truncate_size)
            {
              bytestowrite = truncate_size - totalsize;
              done = 1;
              truncated = 1;
              printf ("Output file needs %d Mbit on flash card, truncating %s, skipping %d bytes\n",
                      truncate_size / MBIT, ucon64.fname, size - (byteswritten + bytestowrite));
            }
          totalsize += bytestowrite;
          if (bytestowrite == 0)
            done = 1;
          fwrite (buffer, 1, bytestowrite, destfile);
          byteswritten += bytestowrite;
        }

      // Be sure the ROM size is a multiple of the buffer size used in
      //  pce_write_rom(), which is 0x4000 (16 kB, so using "buffer" is OK).
      bytestowrite = ((size + 0x3fff) & ~0x3fff) - size;
      if (bytestowrite)
        {
          memset (buffer, 0xff, bytestowrite);
          totalsize += bytestowrite;
          fwrite (buffer, 1, bytestowrite, destfile);
        }

      // pce_write_rom() handles alignment. Games have to be aligned to a Mbit
      //  boundary.
      totalsize = (totalsize + MBIT - 1) & ~(MBIT - 1);
      if (size == 3 * MBIT || size == 4 * MBIT)
        totalsize += 2 * MBIT;
      fclose (srcfile);
      if (truncated)
        break;
    }
  // fill the next game table entry
  fseek (destfile, 0xb000 + (file_no - 1) * 0x20, SEEK_SET);
  fputc (0, destfile);                          // indicate no next game

  // Make it possible for pce_write_rom() to detect that the file is a
  //  multi-game file.
  fseek (destfile, 0xb3f4, SEEK_SET);
  strncpy ((char *) buffer, "uCON64 " UCON64_VERSION_S, 12);
  buffer[12] = 0;
  fwrite (buffer, 1, strlen ((char *) buffer), destfile);

  fclose (destfile);
  ucon64.console = UCON64_PCE;
  ucon64.do_not_calc_crc = org_do_not_calc_crc;

  return 0;
}
示例#14
0
int
ucon64_rom_handling (void)
{
  int no_rom = 0;
  static st_rominfo_t rominfo;
  struct stat fstate;

  ucon64_rom_flush (&rominfo);

  // a ROM (file)?
  if (!ucon64.rom)
    no_rom = 1;
  else if (!ucon64.rom[0])
    no_rom = 1;
  else if (access (ucon64.rom, F_OK | R_OK) == -1 && (!(ucon64.flags & WF_NO_ROM)))
    {
      fprintf (stderr, "ERROR: Could not open %s\n", ucon64.rom);
      no_rom = 1;
    }
  else if (stat (ucon64.rom, &fstate) == -1)
    no_rom = 1;
  else if (S_ISREG (fstate.st_mode) != TRUE)
    no_rom = 1;
#if 0
  // printing the no_rom error message for files of 0 bytes only confuses people
  else if (!fstate.st_size)
    no_rom = 1;
#endif

  if (no_rom)
    {
      if (!(ucon64.flags & WF_NO_ROM))
        {
          fputs ("ERROR: This option requires a file argument (ROM/image/SRAM file/directory)\n", stderr);
          return -1;
        }
      return 0;
    }

  // The next statement is important and should be executed as soon as
  //  possible (and sensible) in this function
  ucon64.file_size = fsizeof (ucon64.rom);
  // We have to do this here, because we don't know the file size until now
  if (ucon64.buheader_len > ucon64.file_size)
    {
      fprintf (stderr,
               "ERROR: A backup unit header length was specified that is larger than the file\n"
               "       size (%d > %d)\n", ucon64.buheader_len, ucon64.file_size);
      return -1;
    }

  if (!(ucon64.flags & WF_INIT))
    return 0;

  // "walk through" <console>_init()
  if (ucon64.flags & WF_PROBE)
    {
      if (ucon64.rominfo)
        {
          // Restore any overrides from st_ucon64_t
          // We have to do this *before* calling ucon64_probe(), *not* afterwards
          if (UCON64_ISSET (ucon64.buheader_len))
            rominfo.buheader_len = ucon64.buheader_len;

          if (UCON64_ISSET (ucon64.interleaved))
            rominfo.interleaved = ucon64.interleaved;

//          ucon64.rominfo = (st_rominfo_t *) &rominfo;
        }
      ucon64.rominfo = ucon64_probe (&rominfo); // determines console type

#ifdef  USE_DISCMAGE
      // check for disc image only if ucon64_probe() failed or --disc was used
      if (ucon64.discmage_enabled)
//        if (!ucon64.rominfo || ucon64.force_disc)
        if (ucon64.force_disc)
          ucon64.image = dm_reopen (ucon64.rom, 0, (dm_image_t *) ucon64.image);
#endif
    }
  // end of WF_PROBE

  // Does the option allow split ROMs?
  if (ucon64.flags & WF_NO_SPLIT)
    /*
      Test for split files only if the console type knows about split files at
      all. However we only know the console type after probing.
    */
    if (ucon64.console == UCON64_NES || ucon64.console == UCON64_SNES ||
        ucon64.console == UCON64_GEN || ucon64.console == UCON64_NG)
      if ((UCON64_ISSET (ucon64.split)) ? ucon64.split : ucon64_testsplit (ucon64.rom))
        {
          fprintf (stderr, "ERROR: %s seems to be split. You have to join it first\n",
                   basename2 (ucon64.rom));
          return -1;
        }


  /*
    CRC32

    Calculating the CRC32 checksum for the ROM data of a UNIF file (NES)
    shouldn't be done with ucon64_fcrc32(). nes_init() uses crc32().
    The CRC32 checksum is used to search in the DAT files, but at the time
    of this writing (Februari the 7th 2003) all DAT files contain checksums
    of files in only one format. This matters for SNES and Genesis ROMs in
    interleaved format and Nintendo 64 ROMs in non-interleaved format. The
    corresponding initialization functions calculate the CRC32 checksum of
    the data in the format of which the checksum is stored in the DAT
    files. For these "problematic" files, their "real" checksum is stored
    in ucon64.fcrc32.
  */
  if (ucon64.crc32 == 0)
    if (!ucon64.force_disc) // NOT for disc images
      if (!(ucon64.flags & WF_NO_CRC32) && ucon64.file_size <= MAXROMSIZE)
        ucon64_chksum (NULL, NULL, &ucon64.crc32, ucon64.rom, ucon64.rominfo ? ucon64.rominfo->buheader_len : 0);


  // DATabase
  ucon64.dat = NULL;
  if (ucon64.crc32 != 0 && ucon64.dat_enabled)
    {
      ucon64.dat = ucon64_dat_search (ucon64.crc32, NULL);
      if (ucon64.dat)
        {
          // detected file size must match DAT file size
          int size = ucon64.rominfo ?
                       UCON64_ISSET (ucon64.rominfo->data_size) ?
                         ucon64.rominfo->data_size :
                         ucon64.file_size - ucon64.rominfo->buheader_len :
                       ucon64.file_size;
          if ((int) (((st_ucon64_dat_t *) ucon64.dat)->fsize) != size)
            ucon64.dat = NULL;
        }

      if (ucon64.dat)
        switch (ucon64.console)
          {
            case UCON64_SNES:
            case UCON64_GEN:
            case UCON64_GB:
            case UCON64_GBA:
            case UCON64_N64:
              // These ROMs have internal headers with name, country, maker, etc.
              break;

            default:
              // Use ucon64.dat instead of ucon64.dat_enabled in case the index
              //  file could not be created/opened -> no segmentation fault
              if (ucon64.dat && ucon64.rominfo)
                {
                  if (!ucon64.rominfo->name[0])
                    strcpy (ucon64.rominfo->name, NULL_TO_EMPTY (((st_ucon64_dat_t *) ucon64.dat)->name));
                  else if (ucon64.console == UCON64_NES)
                    { // override the three-character FDS or FAM name
                      int t = nes_get_file_type ();
                      if (t == FDS || t == FAM)
                        strcpy (ucon64.rominfo->name, NULL_TO_EMPTY (((st_ucon64_dat_t *) ucon64.dat)->name));
                    }

                  if (!ucon64.rominfo->country)
                    ucon64.rominfo->country = NULL_TO_EMPTY (((st_ucon64_dat_t *) ucon64.dat)->country);
                }
              break;
          }
    }

  // display info
  if ((ucon64.flags & WF_NFO || ucon64.flags & WF_NFO_AFTER) && ucon64.quiet < 1)
    ucon64_nfo ();

  return 0;
}