Exemple #1
0
/* Control register changes, adjust ``cti'' (cycle to next interrupt)
 *
 *    This case is a bit tricky : Changing timer prescale on the fly
 *    may have unpredictable result mostly because we dunno how
 *    prescaler works exactly. Here I assume the prescaler is
 *    resetted.
 *
 *    !!! chipmon of synergy does !!!
 *
 */
static inline
void reconf_timer(mfp_timer_t * const ptimer, int tcr, const bogoc68_t bogoc)
{
#if !defined(NDEBUG) || !defined(CPP_SUPPORTS_VA_MACROS)
  uint_t          frq = timerfrq(ptimer->tdr_res); /* old frequency       */
#endif
  const bogoc68_t cti = ptimer->cti - bogoc;       /* cycles to interrupt */
  const uint_t    psw = prediv_width[ptimer->tcr]; /* cycles count-down   */
  const uint_t    cnt = cti/psw;                   /* count-down          */
  const uint_t    psr = cti % psw;
  /* const uint68_t  psc = psw-psr; */

  /* cnt%ptimer->tdr_res+1; no MODULO since TDR may have change and anyway
     cti was calculated with 1 timer cycle !!! */
  const uint_t    tdr = cnt+1;
  const cycle68_t new_psw = prediv_width[(int)tcr];

  if (bogoc > ptimer->cti) {
    TRACE68(mfp_cat,
          MYHD "timer-%c -- reconf out of range -- @%u > cti:%u\n",
          ptimer->def.letter, (unsigned) bogoc, (unsigned) ptimer->cti);
    ptimer->cti = bogoc + psw * ptimer->tdr_res;
  } else {
    ptimer->cti = bogoc + psr + (tdr-1) * new_psw;
    ptimer->cti = bogoc + /* psr + */ (tdr/* -1 */) * new_psw;
  }

  ptimer->tcr = tcr;

  TRACE68(mfp_cat,
          MYHD "timer-%c -- reconf @%u cti:%u cpp:%u -- %u:%uhz\n",
          ptimer->def.letter, (unsigned) bogoc,
          (unsigned) ptimer->cti, (unsigned) cpp(ptimer->tdr_res),
          (unsigned) frq, (unsigned) timerfrq(ptimer->tdr_res));
}
Exemple #2
0
static int isf_close(istream68_t * istream)
{
    istream68_z_t * isf = (istream68_z_t *)istream;
    int err = -1;

    TRACE68(zlib_cat,"istream68_z: close(%s) {\n",
            istream68_filename(istream));

    if (isf) {
        err = isf->is_err;

        if (isf->deflate) {
            TRACE68(zlib_cat,"DEFLATED ");
            isf->deflate = 0;
            if (!err) {
                err = isf_deflate_buffer(isf, 1) == -1;
            }
            TRACE68(zlib_cat,"in:%d out:%d ",
                    isf->c_stream.total_in,isf->c_stream.total_out);
            if (isf->gzip) {
                TRACE68(zlib_cat,"crc:%08X ",isf->c_crc32);
            }
            if (!err) {
                int i, c, t;
                unsigned char hd[8];
                for (i=0, c=isf->c_crc32, t=isf->c_stream.total_in;
                        i<4;
                        ++i, c>>=8, t>>=8) {
                    hd[0+i] = (unsigned char)c;
                    hd[4+i] = (unsigned char)t;
                }
                err = istream68_write(isf->is, hd, 8) != 8;
            }
            deflateEnd(&isf->c_stream);
        }
Exemple #3
0
/* Write Timer Data Register:

   Changing the value of the TDR change the value of the internal
   reset latch. However when the timer is stopped the reset value is
   reload into TDR in the next MFP cycle (so it seems to be the case
   according to my test on a real ST). The tricky point is that as MFP
   and CPU clock are separate (for Atari-ST) reading the value just
   after a write can occur before the next MFP cycle in which case the
   current TDR (not the one written) is returned! Fortunatly we don't
   really need to emulate this since it is more a glitch than anything
   and no one should have used it!

   Motorola Datasheet: the TDRs contain the value of their respective
   main counter. This value was captured on the last low-to-high
   transistion of the data strobe pin. The main counter is initialized
   by writting the to the TDR. If the timer is stopped the data is
   loaded simultaneously into both TDR and maincounter. If the TDR is
   written to while the timer is enabled, the value is not loaded into
   the timer until the timer counts through 01. If a write is
   performed while the timer is counting through 01 then an
   INDETERMINATE value is loaded into the main counter.

*/
void mfp_put_tdr(mfp_t * const mfp, int timer, int68_t v, const bogoc68_t bogoc)
{
  mfp_timer_t * const  ptimer = &mfp->timers[timer&3];
#ifndef NDEBUG
  const uint_t old_tdr = ptimer->tdr_res;
#endif

  /* Interrupt when count down to 0 so 0 is 256 */
  v  = (u8)v; v += (!v)<<8;
  ptimer->tdr_res = v;

  if (!ptimer->tcr) {
    ptimer->tdr_cur = v;
    TRACE68(mfp_cat,
          MYHD "timer-%c -- reload TDR @%u -- %u\n",
            ptimer->def.letter, (unsigned) bogoc, (unsigned) ptimer->tdr_res);
  }
#ifndef NDEBUG
  else if (ptimer->tcr && v != old_tdr) {
    uint_t old_frq = timerfrq(old_tdr);
    TRACE68(mfp_cat,
            MYHD "timer-%c -- change @%u cti:%u psw:%u(%u) cpp:%u"
            " -- %u(%u) -> %u(%u)hz\n",
            ptimer->def.letter, (unsigned) bogoc, (unsigned) ptimer->cti,
            (unsigned) prediv_width[ptimer->tcr], (unsigned) ptimer->tcr,
            (unsigned) cpp(ptimer->tdr_res),
            (unsigned) old_frq, (unsigned) old_tdr,
            (unsigned) timerfrq(ptimer->tdr_res), (unsigned) ptimer->tdr_res);
  }
#endif
}
Exemple #4
0
void mfp_adjust_bogoc(mfp_t * const mfp, const bogoc68_t bogoc)
{
  mfp_timer_t *ptimer;

  if (!bogoc) return;
  for (ptimer = mfp->timers; ptimer != mfp->timers+4; ++ptimer) {
    if (ptimer->tcr) {
      if (ptimer->cti < bogoc) {
        TRACE68(mfp_cat,
              MYHD "timer-%c -- adjust -- cti:%u cycle:%u\n",
              ptimer->def.letter, (unsigned) ptimer->cti, (unsigned) bogoc);
      }
      assert(ptimer->cti >= bogoc);
      while (ptimer->cti < bogoc) {
        /* $$$ !!! SHOULD NOT HAPPEN !!! */
        ++ptimer->int_lost;
        ptimer->cti += cpp(ptimer->tdr_res);
      }
      if (ptimer->int_lost) {
        msg68_critical(MYHD "timer-%c -- adjust has lost interrupt -- %d\n",
                       ptimer->def.letter, ptimer->int_lost);
        ptimer->int_lost = 0;
      }
      ptimer->cti -= bogoc;
    }
  }
}
Exemple #5
0
/* Load config from registry */
static int load_from_registry(const char * confname)
{
  option68_t * opt;
  int err = 0;
  char paths[2][64];

  snprintf(paths[0], sizeof(paths[0]), cuk_fmt, confname);
  strncpy(paths[1], lmk_str, sizeof(paths[1]));

  for (opt = option68_enum(0); opt; opt = opt->next) {
    char path[128], str[512];
    int  k, val;
    if (!opt->save)
      continue;

    for (k=0; k<2; ++k) {
      strncpy(path, paths[k], sizeof(path));
      strncat(path, opt->name, sizeof(path));

      TRACE68(config68_cat, "conf68: trying -- '%s'\n", path);
      switch (opt->type) {
      case opt68_BOL: case opt68_INT:
        err = registry68_geti(0, path, &val);
        if (!err)
          err = option68_iset(opt, val, opt68_PRIO, opt68_CFG);
        if (!err)
          TRACE68(config68_cat,
                  "conf68: load '%s' <- %d\n", path, val);
        break;
      case opt68_ENU: case opt68_STR:
        err = registry68_gets(0, path, str, sizeof(str));
        if (!err)
          err = option68_set(opt, str, opt68_PRIO, opt68_CFG);
          TRACE68(config68_cat,
                  "conf68: load '%s' <- '%s'\n", path, str);
        break;
      default:
        assert(!"invalid option type");
        err = -1;
        break;
      }
    }
  }

  return 0;
}
Exemple #6
0
int config68_save(const char * confname)
{
    return 0;
  int err = 0;
  char tmp[128];
  option68_t * opt;

  confname = confname ? confname : config68_def_name;

  if (!config68_use_registry) {
    /* Save into file */
    vfs68_t * os=0;
    const int sizeof_config_hd = sizeof(config_header)-1;

    strncpy(tmp, "sc68://config/", sizeof(tmp));
    strncat(tmp, confname, sizeof(tmp));
    os = uri68_vfs(tmp, 2, 0);
    err = vfs68_open(os);
    if (!err) {
      TRACE68(config68_cat,"conf68: save into \"%s\"\n",
              vfs68_filename(os));
      err =
        - (vfs68_write(os, config_header, sizeof_config_hd)
           != sizeof_config_hd);
      for (opt = option68_enum(0); opt; opt=opt->next)
        err |= save_config_entry(os, opt);
    }
    vfs68_close(os);
    vfs68_destroy(os);
  } else {
    /* Save into registry */
    int l = snprintf(tmp, sizeof(tmp), cuk_fmt, confname);
    char * s = tmp + l;
    l = sizeof(tmp) - l;

    for (opt = option68_enum(0); opt; opt=opt->next) {
      if (opt->org == opt68_UDF || !opt->save)
        continue;
      strncpy(s,opt->name,l);
      switch (opt->type) {
      case opt68_INT: case opt68_BOL:
        err |= registry68_puti(0, tmp, opt->val.num);
        break;
      case opt68_ENU:
        err |= registry68_puts(0, tmp, opt->val.num[(char**)opt->set]);
        break;
      case opt68_STR:
        err |= registry68_puts(0, tmp, opt->val.str);
        break;
      }
    }

  }

  return err;
}
Exemple #7
0
int config68_init(int argc, char * argv[])
{
  config68_cat = msg68_cat("conf","config file", DEBUG_CONFIG68_O);
  option68_append(opts,sizeof(opts)/sizeof(*opts));
  argc = option68_parse(argc,argv);
  config68_use_registry = !config68_force_file && registry68_support();
  TRACE68(config68_cat,
          "conf68: will use %s\n",
          config68_use_registry?"registry":"config file");
  return argc;
}
Exemple #8
0
/* Resume a stopped timer: tcr 0->!0
 */
static inline
void resume_timer(mfp_timer_t * const ptimer, int tcr, bogoc68_t bogoc)
{
  ptimer->tcr = tcr;
  ptimer->cti = bogoc + ptimer->tdr_cur * prediv_width[tcr] - ptimer->psc;

  TRACE68(mfp_cat,
          MYHD "timer-%c  -- resume @%u cti:%u cpp:%u "
          "tdr:%u/%u psw:%u(%u) -- %uhz\n",
          ptimer->def.letter, (unsigned) bogoc, (unsigned) ptimer->cti,
          (unsigned) cpp(ptimer->tdr_res),
          (unsigned) ptimer->tdr_cur, (unsigned) ptimer->tdr_res,
          (unsigned) prediv_width[ptimer->tcr], (unsigned) ptimer->tcr,
          (unsigned) timerfrq(ptimer->tdr_res));
}
Exemple #9
0
int mw_lmc_mixer(mw_t * const mw, int n)
{
  static const int * const table[3] = { Db_mix12, Db_mix, Db_alone };

  if (n == MW_LMC_QUERY) {
    n = mw->lmc.mixer;
  } else {
    n &= 3;
    mw->lmc.mixer = n;
    if (n != 3) {
      mw->db_conv = table[n];
    } else {
      msg68_warning(MWHD "invalid LMC mixer mode -- %d\n", n);
    }
  }
  TRACE68(mw_cat, MWHD "LMC mixer mode -- *%s*\n",
          mixermode[mw->lmc.mixer]);
  return n;
}
Exemple #10
0
SC68_EXTERN
int dial68_new_conf(void ** pdata, sc68_dial_f * pcntl)
{
  int res = -1;
  const int size = sizeof(dial_t);
  dial_t * dial = (dial_t *) malloc(size);

  if (dial) {
    dial->dial.dial = magic;
    dial->dial.size = size;
    dial->dial.data = *pdata;
    dial->dial.cntl = *pcntl;
    *pcntl = conf;
    *pdata = dial;
    res = 0;
  }
  TRACE68(dial_cat, P "%s -> %p %d\n", __FUNCTION__, (void*)dial, res);
  return res;
}
Exemple #11
0
void mfp_put_tcr(mfp_t * const mfp,
                 int timer, int68_t v, const bogoc68_t bogoc)
{
  timer &= 3;
  if (timer < TIMER_C) {
    /* Timer A or B */
    mfp->map[0x19+2*timer] = v;
    /* $$$ Event mode + Pulse mode is NOT simulate yet ! */
    if (v&0x10) {
      TRACE68(mfp_cat,
            MYHD "timer-%c -- mode not supported --  %02x\n",
            timer_def[timer].letter,(int)(u8)v);
      assert(0 == "mfp mode not supported");
    }
    mfp_put_tcr_bogo(mfp->timers+timer, v&7, bogoc);
  } else {
    /* Timer C and D */
    mfp->map[0x1D] = v;
    mfp_put_tcr_bogo(mfp->timers+TIMER_C, (v>>4)&7, bogoc);
    mfp_put_tcr_bogo(mfp->timers+TIMER_D,  v    &7, bogoc);
  }
}
Exemple #12
0
/* ,-----------------------------------------------------------------.
 * |                   Set/Get replay frequency                      |
 * `-----------------------------------------------------------------'
 */
int mw_sampling_rate(mw_t * const mw, int hz)
{
  switch (hz) {

  case MW_HZ_QUERY:
    hz = mw ? mw->hz : default_parms.hz;
    break;

  case MW_HZ_DEFAULT:
    hz = default_parms.hz;

  default:
    if (hz < SPR_MIN)
      hz = SPR_MIN;
    else if (hz > SPR_MAX)
      hz = SPR_MAX;
    *(mw ? &mw->hz : &default_parms.hz) = hz;
    TRACE68(mw_cat, MWHD "%s sampling rate -- *%dhz*\n",
            mw ? "select" : "default", hz);
    break;
  }
  return hz;
}
Exemple #13
0
static int conf(void * data, const char * key, int op, sc68_dialval_t *val)
{
  dial_t * dial = (dial_t *) data;
  int res = -1;

  static const char * l_spr[] = {
    "< custom >",
    "11 khz","22 khz", "44.1 khz","48 khz","96 khz"
  };
  static const int i_spr[] = {
    0,
    11025, 22050, 44100, 48000, 96000
  };
  const int sprmax = sizeof (l_spr) / sizeof (*l_spr);

  /* Sanity check */
  if (!key || !ismagic(dial))
    goto exit;

  /* Run user control function */
  res = dial->dial.cntl(dial->dial.data, key, op, val);

  /* Kill special case. */
  if (op == SC68_DIAL_CALL && !strcmp(key,SC68_DIAL_KILL)) {
    del_dial(dial);
    goto exit;
  }

  /* User dealt with that message. */
  if (res <= 0)
    goto exit;

  /* Assume no error */
  res = 0;

  if (keyis("sampling")) {
    /* This key is used for the predefined sampling rate */

    switch (op) {

    case SC68_DIAL_CNT:
      val->i = sprmax;
      break;

    case SC68_DIAL_GETI: {
      const option68_t * opt
        = option68_get("sampling-rate", opt68_ISSET);
      if (!opt)
        val->i = 5;                     /* default to 48khz */
      else {
        for (val->i=1; val->i<sprmax; ++val->i)
          if (i_spr[val->i] == opt->val.num)
            break;
        if (val->i >= sprmax)
          val->i = 0;
      }
    } break;

    case SC68_DIAL_ENUM:
      if (val->i >= 0 && val->i < sprmax) {
        val->s = l_spr[val->i];
        break;
      }

    default:
      res = -1;
    }

  }
  else if (op == SC68_DIAL_CALL) {
    /* Other special calls like real-tiem access */
    if (keyis(SC68_DIAL_NEW))
      val->i = 0;
    else if (keyis("save"))
      val->i = sc68_cntl(0, SC68_CONFIG_SAVE);
    else if (keyis("amiga-filter"))
      /* $$$ TODO: realtime amiga-filter */
      val->i = !!val->i;
    else if (keyis("amiga-blend"))
      /* $$$ TODO: realtime amiga-blend */
      val->i = val->i;
  }
  else {
    /* Finally try it as an option key.
     *
     * "sampling-rate" is converted if the value is in the index range
     *                 instead of the frequency value range.
     */
    if (op == SC68_DIAL_SETI && keyis("sampling-rate")
        && val->i > 0 && val->i < sprmax)
        val->i = i_spr[val->i];
    res = getopt(key, op, val);
  }

exit:
  TRACE68(dial_cat, P
          "%s() #%02d \"%s\" -> %d\n", __FUNCTION__, op, key, res);
  return res;
}
Exemple #14
0
/* Load config from file */
static int load_from_file(const char * confname)
{
  vfs68_t * is = 0;
  char s[256], * word;
  int err;
  option68_t * opt;

  strcpy(s, "sc68://config/");
  strcat(s, confname);
  is = uri68_vfs(s, 1, 0);
  err = vfs68_open(is);
  if (err)
    goto error;

  for(;;) {
    char * name;
    int i, len, c = 0;

    len = vfs68_gets(is, s, sizeof(s));
    if (len == -1) {
      err = -1;
      break;
    }
    if (len == 0) {
      break;
    }

    i = 0;

    /* Skip space */
    while (i < len && (c=s[i++], isspace(c)))
      ;

    if (!is_symbol_char(c)) {
      continue;
    }

    /* Get symbol name. */
    name = s+i-1;
    while (i < len && is_symbol_char(c = s[i++]))
      if (c == '_') s[i-1] = c = '-';
    s[i-1] = 0;

    /* TRACE68(config68_cat,"conf68: load get key name='%s\n", name); */

    /* Skip space */
    while (i < len && isspace(c))
      c=s[i++];

    /* Must have '=' */
    if (c != '=') {
      continue;
    }
    c=s[i++];

    /* Skip space */
    while (i < len && isspace(c))
      c=s[i++];

    word = s + i - 1;
    while (i < len && (c = s[i++]) && c != '\n');
    s[i-1] = 0;

    opt = option68_get(name, opt68_ALWAYS);
    if (!opt) {
      TRACE68(config68_cat, "conf68: unknown config key '%s'='%s'\n",
              name, word);
      continue;
    }
    if (!opt->save) {
      TRACE68(config68_cat, "conf68: config key '%s'='%s' not for save\n",
              name, word);
    }

    TRACE68(config68_cat, "conf68: set name='%s'='%s'\n",
            name, word);
    option68_set(opt, word, opt68_PRIO, opt68_CFG);
  }

 error:
  vfs68_destroy(is);
  TRACE68(config68_cat, "conf68: loaded => [%s]\n",strok68(err));
  return err;

}
Exemple #15
0
/* Deflate as much as possible.
 * @return  Number of byte
 */
static int isf_deflate_buffer(istream68_z_t * isf, int finish)
{
    int err = 0, mia, zeof;
    const int z_flush_mode = finish ? Z_FINISH : Z_NO_FLUSH;

    /* fake zeof to avoid flushing */
    zeof = (z_flush_mode != Z_FINISH);

    isf->c_stream.next_in = isf->buffer_in;
    isf->c_stream.avail_in = isf->write_in - isf->buffer_in;

    /* Loop while there is data to compress ... */
    while (!zeof || isf->c_stream.avail_in) {
        /*     TRACE68(zlib_cat,"%sDEFLATE: (%d:%d/%d:%d) ", */
        /*         finish ? "F-" : "", */
        /*         isf->c_stream.next_in - isf->buffer_in, */
        /*         isf->c_stream.avail_in, */
        /*         isf->c_stream.next_out - isf->buffer_out, */
        /*         isf->c_stream.avail_out); */

        /* Flush output buffer and win a fresh one. */
        err = isf_flush_output_buffer(isf);
        if (err == -1) {
            /*       TRACE68(zlib_cat,"\n"); */
            return -1;
        }

        /* Do the deflate thing */
        /*     TRACE68(zlib_cat,"(%d:%d/%d:%d), deflate->", */
        /*         isf->c_stream.next_in - isf->buffer_in, */
        /*         isf->c_stream.avail_in, */
        /*         isf->c_stream.next_out - isf->buffer_out, */
        /*         isf->c_stream.avail_out); */
        {
            Byte * start = isf->c_stream.next_in;
            int len = isf->c_stream.avail_in;
            err = deflate(&isf->c_stream, z_flush_mode);
            if (isf->gzip) {
                isf->c_crc32 = crc32(isf->c_crc32, start, len-isf->c_stream.avail_in);
            }
        }
        /*     TRACE68(zlib_cat,"(%d:%d/%d:%d) ", */
        /*         isf->c_stream.next_in - isf->buffer_in, */
        /*         isf->c_stream.avail_in, */
        /*         isf->c_stream.next_out - isf->buffer_out, */
        /*         isf->c_stream.avail_out); */

        if (err == Z_STREAM_END) {
            /* Zlib tell us this is the end my friend ?? */
            /*       TRACE68(zlib_cat,"Z_STREAM_END!! "); */
            err = isf_flush_output_buffer(isf) == -1;
            zeof = 1;
            break;
        }
        if (err != Z_OK) {
            TRACE68(zlib_cat,"Z_ERROR(%d:[%s])\n", err, isf->c_stream.msg);
            err = -1;
            break;
        } else {
            err = 0;
            /*       TRACE68(zlib_cat,"Z_OK "); */
        }
    }

    /* Are there "Missing In Action" bytes in the input buffer ? */
    mia = isf->c_stream.avail_in;
    /*   TRACE68(zlib_cat,"MIA:%d\n", mia); */

    isf->write_in = isf->buffer_in + mia;
    if (mia > 0) {
        Byte * src = isf->c_stream.next_in;
        int i;
        for (i=0; i<mia; ++i) {
            isf->buffer_in[i] = src[i];
        }
    }

    return err
           ? -1
           : sizeof(isf->buffer_in) - mia;
}
Exemple #16
0
static vfs68_t * default_open(rsc68_t type, const char *name,
                                  int mode, rsc68_info_t * info)
{
  vfs68_t * is = 0;
  int err = -1;
  const char *subdir = 0, *ext = 0;
  char tmp[1024], * apath = 0;
  char tmpname[512];
  int alen = 0;
  char_cv_t cv_path=0, cv_extra=0;
  struct {
    const char * path, * sdir, * ext;
    int curl;
  } pathes[4];
  int ipath, npath = 0;
  const char * share_path  = default_share_path();
  const char * rmusic_path = default_rmusic_path();

  /* default to invalid type. */
  if (info) {
    info->type = rsc68_last;
  }

  if ( (int) type < 0 || (int)type >= rsc68_last) {
    return 0;
  }

  memset(pathes,0,sizeof(pathes));

  if (type == rsc68_music && lmusic_path) {
    /* local music path is prior to user share */
    pathes[npath].path = lmusic_path;
    pathes[npath].sdir = "/";
    ++npath;
  }

  /* Build default pathes list */
  if (user_path) {
    pathes[npath++].path = user_path;
  }

  switch (mode &= 3) {
    case 1: case 2:
      break;
  default:
    assert(!"invalid mode");
    return 0;
  }

  if (mode == 1 && share_path) {
    pathes[npath++].path = share_path;
  }

  subdir = rsc68_table[type].path;
  ext    = rsc68_table[type].ext;

  /* Set a default name for config file if none is given. */
  if (type == rsc68_config && (!name || !name[0])) {
    name = "sc68";
  }

  TRACE68(rsc68_cat,"rsc68: open %c 'sc68://%s/%s%s'\n",
          (mode==1)?'R':'W',rsc68_table[type].name, name, ext?ext:"");

  /* Any specific stuff. */
  switch (type) {
  case rsc68_replay:

#if defined (USE_REPLAY68) && 0

    /* Method using vfs to inflate data. Notice that unfortunatly
     * we can't use a proper Z stream because the replay loader needs
     * to know the length and vfs68_z::length() method does not
     * have this information before it has inflated the all data. This
     * is a limitation that could probably be dealt with, at least
     * with gziped stream as the information is available at the end
     * of the stream. Also in this particular case the inflate size is
     * available via the replay68_get() function.
     */
    if (mode == 1) {
      const void * cdata;
      int csize, dsize;
      vfs68_t * is_in;

      TRACE68(rsc68_cat,"rsc68: trying built-in replay -- %s\n", name);
      if (!replay68_get(name, &cdata, &csize, &dsize)) {
        TRACE68(rsc68_cat,"rsc68: found built-in replay -- %s %d %d\n",
                name, csize, dsize);
        is_in =
          vfs68_z_create(
            vfs68_mem_create(cdata, csize, mode),
            mode|VFS68_SLAVE,
            vfs68_z_default_option);
        if (is_in) {
          is = vfs68_mem_create(0, dsize, 3);
          if (!vfs68_open(is_in) && !vfs68_open(is)) {
            int n;
            while (n = vfs68_read(is_in, tmpname, sizeof(tmpname)), n > 0)
              if (vfs68_write(is, tmpname, n) != n) {
                n = -1;
                break;
              }
            err = -!!n;
          }
          vfs68_destroy(is_in);
          vfs68_seek_to(is,0);
        }
      }
    }

#elif defined (USE_REPLAY68)

    /* Method using gzip68_buffer() is probably faster (less memory
     * copy) than the previous Z stream one. It still need to allocate
     * a temporary buffer to store deflated data whereas a proper
     * vfs could have deflated on the fly into the 68k memory
     * buffer. See previous method comment on that matter.
     */
    if (mode == 1) {
      const void * cdata;
      void * ddata;
      int csize, dsize;

      TRACE68(rsc68_cat,"rsc68: trying built-in replay -- %s\n", name);
      if (!replay68_get(name, &cdata, &csize, &dsize)) {
        TRACE68(rsc68_cat,"rsc68: found built-in replay -- %s %d %d\n",
                name, csize, dsize);
        ddata = malloc(dsize);
        if (ddata) {
          int inflate = gzip68_buffer(ddata, dsize, cdata, csize);
          if (inflate != dsize) {
            msg68_error("rsc68: inflated size of built-in replay differs"
                        " -- %s %d %d\n",name, inflate, dsize);
            err = -1;
          } else {
            is = vfs68_mem_create(ddata, dsize, mode|VFS68_SLAVE);
            if ( (err = -!is) != 0) {
              free(ddata);
            }
          }
        }
      }
    }

#endif

    cv_extra = cv_lower; /* $$$ transform replay name to lower case. */
    break;

  case rsc68_music:
    if (mode == 1 && rmusic_path) {
      pathes[npath].path = rmusic_path;
      pathes[npath].sdir = "/";
      pathes[npath].curl = 1;
      ++npath;
    }
    name = convert_music_path(tmpname, sizeof(tmpname), name, info);
    break;

  default:
    break;
  }

  for (ipath=0; !is && name && ipath < npath; ++ipath) {
    const char *cpath, * cdir, * cext;
    char *p, *pe, *path;
    int len, l;

    cpath = pathes[ipath].path;
    cdir  = pathes[ipath].sdir ? pathes[ipath].sdir : subdir;
    cext  = pathes[ipath].ext ? pathes[ipath].ext : ext;

    len = 1
      + strlen(cpath)
      + strlen(cdir)
      + strlen(name)
      + (cext ? strlen(cext) : 0);

    if (len <= alen) {
      path = apath;
    } else if (len  <= sizeof(tmp)) {
      path = tmp;
    } else {
      free(apath);
      apath = malloc(len);
      alen = apath ? len : 0;
      path = apath;
    }

    if (!path) {
      continue;
    }

    p = path;
    pe = path + len;

    cv_path = pathes[ipath].curl
      ? cv_path_remote
      : cv_path_local;

    /* Build path. */
    l = copy_path(p, pe-p, cpath, cv_path, 0 , 0);
    p += l;
    l = copy_path(p, pe-p, cdir, cv_path, 0, 0);
    p += l;
    l = copy_path(p, pe-p, name, cv_path, cv_extra, 0);
    p += l;
    if (cext) {
      l = copy_path(p, pe-p, cext, 0, 0 ,0);
      p += l;
    }

    is = uri68_vfs(path, mode, 0);
    err = vfs68_open(is);
    TRACE68(rsc68_cat, "rsc68: try [%s]\n", strok68(err));
    if (!err)
      break;

    vfs68_destroy(is);
    is = 0;
  }

  if (apath != tmp)
    free(apath);
  if (err) {
    vfs68_destroy(is);
    is = 0;
  }

  if (is && info)
    info->type = type;

  TRACE68(rsc68_cat, "rsc68: open '%s' -- *%s*\n",
          vfs68_filename(is),
          strok68(!is));
  return is;
}
Exemple #17
0
/* Inflate as much as possible.
 * returns number of byte available in out buffer
 */
static int isf_inflate_buffer(istream68_z_t * isf)
{
    int err, n;
    err = 0;
    isf->c_stream.avail_out = sizeof(isf->buffer_out);
    isf->c_stream.next_out = isf->read_out = isf->buffer_out;

    while (isf->c_stream.avail_out) {

        /*     TRACE68(zlib_cat,"INFLATE: (%d,%d)", */
        /*         isf->c_stream.avail_in, isf->c_stream.avail_out); */
        if (!isf->c_stream.avail_in) {
            err = isf_fill_input_buffer(isf,sizeof(isf->buffer_in));
            /*       TRACE68(zlib_cat," fill_in(%d) ",err); */
            if (err <= 0) {
                break;
            }
        }
        /*     TRACE68(zlib_cat," (%d,%d), inflate->", */
        /*         isf->c_stream.avail_in, isf->c_stream.avail_out); */
        err = inflate(&isf->c_stream, Z_NO_FLUSH);
        /*     TRACE68(zlib_cat,"(%d,%d)", isf->c_stream.avail_in, isf->c_stream.avail_out); */

        if (err == Z_STREAM_END) {
            /*       TRACE68(zlib_cat," Z_STREAM_END\n"); */
            if (isf->gzip) {
                unsigned char data[8];

                err = isf_read_buffer(isf, data, 8);
                if (err >= 4) {
                    isf->gz_crc32 = data[0]
                                    | (data[1]<<8)
                                    | (data[2]<<16)
                                    | (data[3]<<24);
                }
                if (err >= 8) {
                    isf->gz_len = data[4]
                                  | (data[5]<<8)
                                  | (data[6]<<16)
                                  | (data[7]<<24);
                }
                TRACE68(zlib_cat,"Total In  : %8d\n"
                        "Total Out : %8d\n"
                        "Crc32     : %08X\n"
                        "Gzip-Size : %8d\n",
                        isf->c_stream.total_in,
                        isf->c_stream.total_out,
                        isf->gz_crc32,
                        isf->gz_len);
            }
            err = 0;
            break;
        } else if (err == Z_OK) {
            /*       TRACE68(zlib_cat," Z_STREAM_OK\n"); */
            err = 0;
        } else {
            TRACE68(zlib_cat,"Z_ERROR:[%s]\n", isf->c_stream.msg);
            break;
        }

    }

    n = isf->c_stream.next_out - isf->buffer_out;
    if (isf->gzip) {
        isf->c_crc32 = crc32(isf->c_crc32, isf->buffer_out, n);
        /*     TRACE68(zlib_cat,"CRC32:%08X\n",isf->c_crc32); */
    }

    return err
           ? -1
           : n;
}
Exemple #18
0
static int getopt(const char * key, int op, sc68_dialval_t * val)
{
  option68_t * opt = option68_get(key, opt68_ALWAYS);
  const int org = opt68_CFG;

  if (opt) {
    const int isset = opt->org != opt68_UDF;

    TRACE68(dial_cat,
            P "Got an option \"%s\" %sset opcode:%d\n",
            key, isset?"":"not ", op);

    switch (op) {

    case SC68_DIAL_GETI:
      if (isset && (opt->type == opt68_BOL ||
                    opt->type == opt68_INT ||
                    opt->type == opt68_ENU)) {
        val->i = opt->val.num;
        return 0;
      }
      break;

    case SC68_DIAL_GETS:
      if (isset && opt->type == opt68_STR) {
        val->s = opt->val.str;
        return 0;
      }
      break;

    case SC68_DIAL_ENUM:
      if (isset && opt->type == opt68_ENU &&
          val->i >= 0 && val->i < (int)opt->sets) {
        val->s = val->i[(const char **)opt->set];
        return 0;
      }
      break;

    case SC68_DIAL_SETI:
      return option68_iset(opt, val->i, opt68_ALWAYS, org);

    case SC68_DIAL_SETS:
      return option68_set(opt, val->s, opt68_ALWAYS, org);

    case SC68_DIAL_MIN:
      val->i = opt->min;
      return 0;

    case SC68_DIAL_MAX:
      val->i = opt->max;
      return 0;

    case SC68_DIAL_CNT:
      val->i = opt->sets;
      return 0;

    case SC68_DIAL_CAT:
      val->s = opt->cat;
      return 0;

    case SC68_DIAL_DESC:
      val->s = opt->desc;
      return 0;


    }
  }

  return -1;
}
Exemple #19
0
static
int finf(void * data, const char * key, int op, sc68_dialval_t *val)
{
    dial_t * const dial = data;
    int res;

    /* Sanity check */
    if (!key || !ismagic(dial))
        return -1;

    /* Run user control function */
    res = dial->dial.cntl(dial->dial.data, key, op, val);
    TRACE68(dial_cat,P "user-cntl #%02d \"%s\" -> %d\n", op, key, res);

    /* Kill special case. */
    if (op == SC68_DIAL_CALL && keyis(SC68_DIAL_KILL)) {
        del_dial(dial);
        res = 0;
    }

    /* User dealt with that message. */
    if (res <= 0)
        goto exit;

    /* Assume no error */
    res = 0;

    if (op == SC68_DIAL_CALL && keyis(SC68_DIAL_NEW)) {
        if (!dial->dial.cntl(dial->dial.data, "sc68", op, val))
            dial->sc68 = (sc68_disk_t) val->s;
        if (!dial->dial.cntl(dial->dial.data, "disk", op, val))
            dial->disk = (sc68_disk_t) val->s;
        TRACE68(dial_cat, P "\"%s\" sc68:%p disk:%p\n",
                key, dial->sc68, dial->disk);
        val->i = sc68_music_info(dial->sc68,&dial->info,1,dial->disk);
        if (!val->i) {
            TRACE68(dial_cat, P "Got info: %02d - %s - %s\n",
                    dial->info.tracks, dial->info.album, dial->info.title);
        }
    } else if (keyis("track")) {
        int track;
        switch (op) {

        case SC68_DIAL_CNT:
            val->i = dial->info.tracks; /* get count current */
            return 0;

        case SC68_DIAL_GETI:
            val->i = dial->info.trk.track - 1; /* get current */
            return 0;

        case SC68_DIAL_SETI:
            track = (int) val->i + 1;
            if (track <= 0 || track > dial->info.tracks)
                track = dial->info.dsk.track;
            if (track != dial->info.trk.track)
                sc68_music_info(dial->sc68, &dial->info, track, dial->disk);
            val->i = dial->info.trk.track - 1;
            return 0;

        case SC68_DIAL_ENUM:
            track = val->i;
            if (track >= 0 && track < dial->info.tracks) {
                ++track;
                dial->tstr[0] = '0' + (track/10u);
                dial->tstr[1] = '0' + (track%10u);
                dial->tstr[2] = 0;
                val->s = dial->tstr;
            } else {
                TRACE68(dial_cat, P "invalid index \"%s[%d]\"", key,track);
                val->s = "";
                res = -1;
            }
            break;

        default:
            res = -1;
        }
    } else {

        switch (op) {

        case SC68_DIAL_GETS:
            /* if (keyis("uri")) */
            /*   val->s = dial->uri; */
            /* else */
            if (keyis("format"))
                val->s = dial->info.format;
            else if (keyis("genre"))
                val->s = dial->info.genre;
            else if (keyis("title"))
                val->s = dial->info.title;
            else if (keyis("artist"))
                val->s = dial->info.artist;
            else if (keyis("album"))
                val->s = dial->info.album;
            else if (keyis("ripper"))
                val->s = dial->info.ripper;
            else if (keyis("converter"))
                val->s = dial->info.converter;
            else if (keyis("year"))
                val->s = dial->info.year;
            else
                res = -1;
            break;

        case SC68_DIAL_GETI:
            if (keyis("time"))
                val->i = (dial->info.trk.time_ms+500u)/1000u;
            else if (keyis("hw_ym"))
                val->i = dial->info.trk.ym;
            else if (keyis("hw_ste"))
                val->i = dial->info.trk.ste;
            else if (keyis("hw_asid"))
                val->i = dial->info.trk.asid;
            else if (keyis("tag-key"))
                val->i = 0;
            else
                res = -1;
            break;

        case SC68_DIAL_ENUM:
            if (keyis("tag-key") || keyis("tag-val")) {
                const int a = dial->info.dsk.tags;
                const int n = a + dial->info.trk.tags;
                if (val->i >= 0 && val->i<n) {
                    val->s = val->i < a
                             ? ( key[4] == 'k'
                                 ? dial->info.dsk.tag[val->i].key
                                 : dial->info.dsk.tag[val->i].val )
                             : ( key[4] == 'k'
                                 ? dial->info.trk.tag[val->i-a].key
                                 : dial->info.trk.tag[val->i-a].val )
                             ;
                    break;
                } else {
                    TRACE68(dial_cat, P "index out of range \"%s\"[%d] > %d\n",
                            key,val->i,n);
                    res = -1;
                }
            }
            break;

        default:
            res = -1;
        }
    }

exit:
    if (op == SC68_DIAL_CNT) {
        TRACE68(dial_cat, P
                "%s() \"%s\"[#] -> %d (%d)\n",
                __FUNCTION__, key, val->i, res);
    }

    if (op == SC68_DIAL_GETI) {
        TRACE68(dial_cat, P
                "%s() \"%s\" -> %d (%d)\n",
                __FUNCTION__, key, val->i, res);
    }

    if (op == SC68_DIAL_GETS || op == SC68_DIAL_ENUM) {
        TRACE68(dial_cat, P
                "%s() \"%s\" -> \"%s\" (%d)\n",
                __FUNCTION__, key, !res?val->s:"<not-set>", res);
    }

    TRACE68(dial_cat, P
            "%s() #%02d \"%s\" -> %d\n",
            __FUNCTION__, op, key, res);
    return res;
}