Esempio n. 1
0
/**
 * open_buffer - function to open a direct-access buffer
 * @secondary: secondary address used
 *
 * This function is called when the computer wants to open a direct
 * access buffer (#).
 */
static void open_buffer(uint8_t secondary) {
  buffer_t *buf,*prev;
  uint8_t count;

  if (command_length == 3 && command_buffer[1] == '#') {
    /* Open a large buffer */
    count = command_buffer[2] - '0';
    if (count == 0)
      return;

    /* Allocate a chain of linked buffers */
    buf = alloc_linked_buffers(count);
    if (buf == NULL)
      return;

    do {
      buf->secondary = BUFFER_SEC_CHAIN - secondary;
      buf->refill    = directbuffer_refill;
      buf->cleanup   = largebuffer_cleanup;
      buf->read      = 1;
      buf->lastused  = 255;
      stick_buffer(buf);
      mark_write_buffer(buf);
      prev = buf;
      buf = buf->pvt.buffer.next;
    } while (buf != NULL);

    prev->sendeoi = 1;
    buf = prev->pvt.buffer.first;

    /* Set the first buffer as active by using the real secondary */
    buf->secondary = secondary;

  } else {
    /* Normal buffer request */
    // FIXME: This command can specify a specific buffer number.
    buf = alloc_buffer();
    if (!buf)
      return;

    buf->secondary = secondary;
    buf->read      = 1;
    buf->position  = 1;  /* Sic! */
    buf->lastused  = 255;
    buf->sendeoi   = 1;
    buf->pvt.buffer.size  = 1;
    /* directbuffer_refill is used to check for # buffers in iec.c */
    buf->refill           = directbuffer_refill;
    buf->pvt.buffer.first = buf;
    mark_write_buffer(buf);
    stick_buffer(buf);
  }
  return;
}
Esempio n. 2
0
static void eefs_open_read(path_t *path, cbmdirent_t *dent, buffer_t *buf) {
  eefs_error_t res;

  repad_filename(dent->name);

  res = eepromfs_open(dent->name, &buf->pvt.eefh, EEFS_MODE_READ);
  translate_error(res);

  if (res != EEFS_ERROR_OK)
    return;

  /* set up the buffer */
  buf->read   = 1;
  buf->refill = eefs_refill_read;
  // no cleanup/close function needed for read-only files
  stick_buffer(buf);

  buf->refill(buf);
}
Esempio n. 3
0
/**
 * load_directory - Prepare directory generation and create header
 * @secondary: secondary address used for reading the directory
 *
 * This function prepeares directory reading and fills the buffer
 * with the header line of the directory listing.
 * BUG: There is a not-well-known feature in the 1541/1571 disk
 * drives (and possibly others) that returns unparsed directory
 * sectors if $ is opened with a secondary address != 0. This
 * is not emulated here.
 */
static void load_directory(uint8_t secondary) {
  buffer_t *buf;
  path_t path;
  uint8_t pos=1;

  buf = alloc_buffer();
  if (!buf)
    return;

  uint8_t *name;

  buf->secondary = secondary;
  buf->read      = 1;
  buf->lastused  = 31;

  if (command_length > 2 && secondary == 0) {
    if(command_buffer[1]=='=') {
      if(command_buffer[2]=='P') {
        /* Parse Partition Directory */

        /* copy static header to start of buffer */
        memcpy_P(buf->data, dirheader, sizeof(dirheader));
        memcpy_P(buf->data + 32, syspart_line, sizeof(syspart_line));
        buf->lastused  = 63;

        /* set partition number */
        buf->data[HEADER_OFFSET_DRIVE] = max_part;

        /* Let the refill callback handle everything else */
        buf->refill = pdir_refill;

        if(command_length>3) {
          /* Parse the name pattern */
          if (parse_path(command_buffer+3, &path, &name, 0))
            return;

          buf->pvt.pdir.matchstr = name;
        }
        stick_buffer(buf);

        return;
      } else if(command_buffer[2]=='T') {
        buf->pvt.dir.format = DIR_FMT_CMD_SHORT;
        pos=3;
      }
    }
  }

  if (command_buffer[pos]) { /* do we have a path to scan? */
    if (command_length > 2) {
      /* Parse the name pattern */
      if (parse_path(command_buffer+pos, &path, &name, 0))
        return;

      if (opendir(&buf->pvt.dir.dh, &path))
        return;

      buf->pvt.dir.matchstr = name;

      /* Check for a filetype match */
      name = ustrchr(name, '=');
      if (name != NULL) {
        *name++ = 0;
        switch (*name) {
        case 'S':
          buf->pvt.dir.filetype = TYPE_SEQ;
          break;

        case 'P':
          buf->pvt.dir.filetype = TYPE_PRG;
          break;

        case 'U':
          buf->pvt.dir.filetype = TYPE_USR;
          break;

        case 'R':
          buf->pvt.dir.filetype = TYPE_REL;
          break;

        case 'C': /* This is guessed, not verified */
          buf->pvt.dir.filetype = TYPE_CBM;
          break;

        case 'B': /* CMD compatibility */
        case 'D': /* Specifying DEL matches everything anyway */
          buf->pvt.dir.filetype = TYPE_DIR;
          break;

        case 'H': /* Extension: Also show hidden files */
          buf->pvt.dir.filetype = FLAG_HIDDEN;
          break;
        }
        if(buf->pvt.dir.filetype) {
          name++;
          if(*name++ != ',') {
            goto scandone;
          }
        }
        while(*name) {
          switch(*name++) {
          case '>':
            if(parse_date(&date_match_start,&name))
              goto scandone;
            if(date_match_start.month && date_match_start.day) // ignore 00/00/00
              buf->pvt.dir.match_start = &date_match_start;
            break;
          case '<':
            if(parse_date(&date_match_end,&name))
              goto scandone;
            if(date_match_end.month && date_match_end.day) // ignore 00/00/00
              buf->pvt.dir.match_end = &date_match_end;
            break;
          case 'L':
            /* don't switch to long format if 'N' has already been sent */
            if(buf->pvt.dir.format != DIR_FMT_CBM)
              buf->pvt.dir.format = DIR_FMT_CMD_LONG;
            break;
          case 'N':
            buf->pvt.dir.format=DIR_FMT_CBM; /* turn off extended listing */
            break;
          default:
            goto scandone;
          }
          if(*name && *name++ != ',') {
            goto scandone;
          }
        }
      }
    } else {
      /* Command string is two characters long, parse the drive */
      if (command_buffer[1] == '0')
        path.part = current_part;
      else
        path.part = command_buffer[1] - '0' - 1;
      if (path.part >= max_part) {
        set_error(ERROR_DRIVE_NOT_READY);
        return;
      }
      path.dir = partition[path.part].current_dir;
      if (opendir(&buf->pvt.dir.dh, &path))
        return;
    }
  } else {
    path.part = current_part;
    path.dir  = partition[path.part].current_dir;  // if you do not do this, get_label will fail below.
    if (opendir(&buf->pvt.dir.dh, &path))
      return;
  }

scandone:
  if (secondary != 0) {
    /* Raw directory */

    if (partition[path.part].fop == &d64ops) {
      /* No need to fake it for D64 files */
      d64_raw_directory(&path, buf);
      return;
    }

    /* prepare a fake BAM sector */
    memset(buf->data, 0, 256);
    memset(buf->data + BAM_OFFSET_NAME - 2, 0xa0, BAM_A0_AREA_SIZE);

    /* fill label and id */
    if (dir_label(&path, buf->data + BAM_OFFSET_NAME - 2))
      return;

    if (disk_id(&path, buf->data + BAM_OFFSET_ID - 2))
      return;

    /* change padding of label and id to 0xa0 */
    name = buf->data + BAM_OFFSET_NAME - 2 + CBM_NAME_LENGTH;
    while (*--name == ' ')
      *name = 0xa0;

    if (buf->data[BAM_OFFSET_ID+2-2] == 0x20)
      buf->data[BAM_OFFSET_ID+2-2] = 0xa0;

    /* DOS version marker */
    buf->data[0] = 'A';

    buf->refill = rawdir_refill;
    buf->lastused = 253;
  } else {

    /* copy static header to start of buffer */
    memcpy_P(buf->data, dirheader, sizeof(dirheader));

    /* set partition number */
    buf->data[HEADER_OFFSET_DRIVE] = path.part+1;

    /* read directory name */
    if (dir_label(&path, buf->data+HEADER_OFFSET_NAME))
      return;

    /* read id */
    if (disk_id(&path,buf->data+HEADER_OFFSET_ID))
      return;

    /* Let the refill callback handle everything else */
    buf->refill = dir_refill;
  }

  /* Keep the buffer around */
  stick_buffer(buf);

  return;

}