Пример #1
0
void convert(char *src_path, char *dst_path) {
    printf("Converting %s... ", src_path); fflush(stdout);
    Clock clock; clock.tic();

    int uid, iid, nr_us=0, nr_is=0, nr_rs; float rate; double sum = 0;
    FILE *f = fopen(src_path, "r"); if(!f) exit_file_error(src_path);
    std::vector<Node> rs; 

    while(fscanf(f,"%d %d %f\n",&uid,&iid,&rate)!=EOF) {
        if(uid+1>nr_us) nr_us = uid+1; if(iid+1>nr_is) nr_is = iid+1; sum += rate;
        Node r; r.uid=uid, r.iid=iid, r.rate=rate; rs.push_back(r);
    }
    nr_rs = rs.size(); fclose(f);

    Matrix *R = new Matrix(nr_rs,nr_us,nr_is,sum/nr_rs);

    for(auto it=rs.begin(); it!=rs.end(); it++) R->M[it-rs.begin()] = (*it); 

    printf("done. %.2f\n", clock.toc()); fflush(stdout);

    R->write(dst_path);

    delete R;
}
Пример #2
0
static void
play_kcfile(const char* filename, KCFileFormat format)
{
  FILE*        kcfile;
  unsigned int length  = UINT_MAX;
  unsigned int load    = UINT_MAX;
  unsigned int end     = UINT_MAX;
  unsigned int start   = UINT_MAX;
  int          blocknr = 1;
  int          nblocks = INT_MAX / 128;
  wchar_t      name[12];
  uint8_t      block[128];

  if (format == KC_FORMAT_ANY)
  {
    format = kc_format_from_filename(filename);

    if (format == KC_FORMAT_ANY)
      format = KC_FORMAT_TAP;
  }

  if (filename[0] == '-' && filename[1] == '\0')
    kcfile = stdin;
  else
    if (!(kcfile = fopen(filename, "rb")))
      kc_exit_error(filename);

  switch (KC_BASE_FORMAT(format))
  {
    case KC_FORMAT_TAP:
    {
      if (fread(block, KC_TAP_MAGIC_LEN + 1, 1, kcfile) == 0)
        exit_file_error(kcfile, filename);

      if (memcmp(block, KC_TAP_MAGIC, KC_TAP_MAGIC_LEN) != 0)
      {
        fputs("TAP file ID not found\n", stderr);
        exit(1);
      }
      blocknr = block[KC_TAP_MAGIC_LEN];

      if (fread(block, sizeof block, 1, kcfile) == 0)
        exit_file_error(kcfile, filename);
      break;
    }
    case KC_FORMAT_KCC:
    {
      if (fread(block, sizeof block, 1, kcfile) == 0)
        exit_file_error(kcfile, filename);

      load = block[17] | (unsigned)block[18] << 8;
      end  = block[19] | (unsigned)block[20] << 8;

      int nargs = block[16];

      if (nargs >= 3)
        start = block[21] | (unsigned)block[22] << 8;

      if (nargs < 2 || nargs > 10 || load >= end)
      {
        fprintf(stderr, "%s: Invalid KCC start block\n", filename);
        exit(1);
      }
      nblocks = (128 + 127 + end - load) / 128;
      break;
    }
    case KC_FORMAT_SSS:
    {
      kc_filename_to_tape(format, filename, block);

      if (fread(&block[11], 2, 1, kcfile) == 0)
        exit_file_error(kcfile, filename);

      length  = block[11] | (unsigned)block[12] << 8;
      nblocks = (14 + 127 + length) / 128;

      if (fread(&block[13], MIN(length + 1, sizeof block - 13), 1, kcfile) == 0)
        exit_file_error(kcfile, filename);

      if (length < sizeof block - 14)
        memset(&block[14 + length], 0, sizeof block - 14 - length);
      break;
    }
    default:
      abort();
  }

  if (stdout_isterm)
  {
    for (int i = 0; i < 11; ++i)
      name[i] = kc_to_wide_char(block[i]);
    name[11] = L'\0';

    printf("%ls", name);

    if (load != UINT_MAX)
    {
      printf(" %.4X %.4X", load, end);

      if (start != UINT_MAX)
        printf(" %.4X", start);
    }
    putchar('\n');
  }

  play_ramp(1);

  // The initial lead-in sound is played for about 8000 oscillations according
  // to the original documentation.  That length is useful for seeking on tape,
  // but otherwise not required.  About one second (at 1200 Hz) is more than
  // enough.
  for (int i = 0; i < PRE_CYCLES; ++i)
    play_bit(BIT_1);

  play_block(blocknr, block);

  for (int i = 2; i <= nblocks; ++i)
  {
    if (KC_BASE_FORMAT(format) == KC_FORMAT_TAP)
    {
      blocknr = getc(kcfile);

      if (blocknr == EOF)
      {
        if (ferror(kcfile))
          kc_exit_error(filename);

        break; // end of TAP file
      }
    }
    else if (KC_BASE_FORMAT(format) == KC_FORMAT_KCC && i == nblocks)
      blocknr = 0xFF;
    else
      blocknr = i & 0xFF;

    size_t readsize = sizeof block;

    if (KC_BASE_FORMAT(format) == KC_FORMAT_SSS && i == nblocks)
    {
      readsize = length + sizeof block + 14 - nblocks * sizeof block;
      memset(&block[readsize], 0, sizeof block - readsize);
    }
    if (fread(block, readsize, 1, kcfile) == 0)
      exit_file_error(kcfile, filename);

    if (KC_BASE_FORMAT(format) == KC_FORMAT_TAP && blocknr == 1)
    {
      if (stdout_isterm)
      {
        for (int i = 0; i < 11; ++i)
          name[i] = kc_to_wide_char(block[i]);
        name[11] = L'\0';

        printf("\n%ls\n", name);
      }
      for (int i = 0; i < PRE_CYCLES; ++i)
        play_bit(BIT_1);
    }
    play_block(blocknr, block);
  }

  // For BASIC tape images (SSS), send the last block twice: first with the
  // normally incremented block number, and a second time with block number
  // FF.  This is how the original hardware behaves -- probably to maintain
  // compatibility with other home computers of the time.
  if (KC_BASE_FORMAT(format) == KC_FORMAT_SSS)
    play_block(0xFF, block);

  play_ramp(-1);

  if (stdout_isterm)
    putchar('\n');

  while (periodpos > 0)
    play_frame(0);

  if (kcfile != stdin && fclose(kcfile) != 0)
    kc_exit_error(filename);
}