示例#1
0
文件: fileops.c 项目: cbmeeks/sd2iec
/**
 * dir_refill - generate the next directory entry
 * @buf: buffer to be used
 *
 * This function generates a single directory entry with the next matching
 * file. If there is no more matching file the footer will be generated
 * instead. Used as a callback during directory generation.
 */
static uint8_t dir_refill(buffer_t *buf) {
  cbmdirent_t dent;

  uart_putc('+');

  buf->position = 0;

  if (buf->pvt.dir.counter) {
    /* Redisplay image file as directory */
    buf->pvt.dir.counter = 0;
    memcpy(&dent, buf->data+256-sizeof(dent), sizeof(dent));
    dent.typeflags = TYPE_DIR;
    createentry(&dent, buf, buf->pvt.dir.format);
    return 0;
  }

  switch (next_match(&buf->pvt.dir.dh,
                     buf->pvt.dir.matchstr,
                     buf->pvt.dir.match_start,
                     buf->pvt.dir.match_end,
                     buf->pvt.dir.filetype,
                     &dent)) {
  case 0:
    if (image_as_dir != IMAGE_DIR_NORMAL &&
        dent.opstype == OPSTYPE_FAT &&
        check_imageext(dent.pvt.fat.realname) != IMG_UNKNOWN) {
      if (image_as_dir == IMAGE_DIR_DIR) {
        dent.typeflags = (dent.typeflags & 0xf0) | TYPE_DIR;
      } else {
        /* Prepare to redisplay image file as directory */
        buf->pvt.dir.counter = 1;
        /* Use the end of the buffer as temporary storage */
        memcpy(buf->data+256-sizeof(dent), &dent, sizeof(dent));
      }
    }
    createentry(&dent, buf, buf->pvt.dir.format);
    return 0;

  case -1:
    return dir_footer(buf);

  default:
    free_buffer(buf);
    return 1;
  }
}
示例#2
0
文件: display.c 项目: cbmeeks/sd2iec
static void menu_chdir(void) {
  cbmdirent_t dent;
  dh_t    dh;
  path_t  path;
  int8_t  res;

  menustate = MENU_CHDIR;
  display_menu_reset();
  ustrcpy_P(displaybuffer,PSTR("\xc3""ANCEL"));
  display_menu_add(displaybuffer);

  displaybuffer[0] = '_';
  displaybuffer[1] = 0;
  display_menu_add(displaybuffer);

  path.part = current_part;
  path.dir  = partition[current_part].current_dir;

  if (opendir(&dh, &path)) {
    menustate = MENU_NONE;
    return;
  }

  while (1) {
    res = readdir(&dh, &dent);

    if (res > 0)
      return;
    if (res < 0)
      break;

    /* Skip hidden files and only add image files on FAT */
    if (!(dent.typeflags & FLAG_HIDDEN)) {
      if ((dent.typeflags & TYPE_MASK) == TYPE_DIR) {
        display_menu_add(dent.name);
      } else if (dent.opstype == OPSTYPE_FAT &&
                 check_imageext(dent.pvt.fat.realname) != IMG_UNKNOWN) {
        display_menu_add(dent.name);
      }
    }
  }
  display_menu_show(0);
}
示例#3
0
文件: fileops.c 项目: cbmeeks/sd2iec
/**
 * rawdir_refill - generate the next raw directory entry
 * @buf: buffer to be used
 *
 * This function generates a single raw directory entry for the next file.
 * Used as a callback during directory generation.
 */
static uint8_t rawdir_refill(buffer_t *buf) {
  cbmdirent_t dent;

  memset(buf->data, 0, 32);

  if ((buf->pvt.dir.counter & 0x80) == 0) {
    switch (readdir(&buf->pvt.dir.dh, &dent)) {
    case -1:
      /* last entry, switch to dummy entries */
      return rawdir_dummy_refill(buf);

    default:
      /* error in readdir */
      free_buffer(buf);
      return 1;

    case 0:
      /* entry found, creation below */
      break;
    }

    if (image_as_dir != IMAGE_DIR_NORMAL &&
        dent.opstype == OPSTYPE_FAT &&
        check_imageext(dent.pvt.fat.realname) != IMG_UNKNOWN) {
      if (image_as_dir == IMAGE_DIR_DIR) {
        dent.typeflags = (dent.typeflags & 0xf0) | TYPE_DIR;
      } else {
        /* Prepare to redisplay image file as directory */
        buf->pvt.dir.counter |= 0x80;
        memcpy(buf->data+256-sizeof(dent), &dent, sizeof(dent));
      }
    }
  } else {
    /* Redisplay image file as directory */
    buf->pvt.dir.counter &= 0x7f;
    memcpy(&dent, buf->data+256-sizeof(dent), sizeof(dent));
    dent.typeflags = TYPE_DIR;
  }

  buf->data[DIR_OFS_TRACK]     = 1;
  buf->data[DIR_OFS_SIZE_LOW]  = dent.blocksize & 0xff;
  buf->data[DIR_OFS_SIZE_HI ]  = dent.blocksize >> 8;
  buf->data[DIR_OFS_FILE_TYPE] = dent.typeflags ^ FLAG_SPLAT;

  /* Copy file name without 0-byte */
  memset(buf->data + DIR_OFS_FILE_NAME, 0xa0, CBM_NAME_LENGTH);
  memcpy(buf->data + DIR_OFS_FILE_NAME, dent.name, ustrlen(dent.name));

  /* Every 8th entry is two bytes shorter   */
  /* because the t/s link bytes are skipped */
  if ((buf->pvt.dir.counter++) & 0x7f)
    buf->position = 0;
  else
    buf->position = 2;

  buf->lastused = 31;

  if ((buf->pvt.dir.counter & 0x7f) == 8)
    buf->pvt.dir.counter &= 0x80;

  return 0;
}
示例#4
0
void menu_browse_files(void) {
  buffer_t *buf;
  buffer_t *buf_tbl;
  buffer_t *buf_cur;
  buffer_t *first_buf;
  path_t path;
  cbmdirent_t dent;
  uint16_t entries;
  uint8_t entry_num;
  bool fat_filesystem;
  uint8_t i;
  uint8_t my;
  uint16_t mp;
  bool action;
  uint16_t stack_mp[MAX_LASTPOS];
  uint8_t stack_my[MAX_LASTPOS];
  uint8_t pos_stack;
  uint8_t save_active_buffers;

  pos_stack = 0;
  memset(stack_mp, 0, sizeof(stack_mp));
  memset(stack_my, 0, sizeof(stack_my));
  save_active_buffers = active_buffers;

start:
  lcd_clear();
  lcd_puts_P(PSTR("Reading..."));

  buf = buf_tbl = buf_cur = first_buf = NULL;
  entries = entry_num = mp = 0;
  fat_filesystem = false;

  // Allocate one buffer, used to read a single directory entry
  if ((buf = alloc_system_buffer()) == NULL) return;

  // Allocate buffers with continuous data segments
  // Stores pointers to directory entries for qsort
  if ((buf_tbl = alloc_linked_buffers(CONFIG_DIR_BUFFERS)) == NULL) return;

  // Buffers to store the actual diretory entries.
  // Whilst the directory grows, new buffers get allocated and linked
  if ((buf_cur = alloc_system_buffer()) == NULL) return;
  first_buf = buf_cur;

  // Allocating buffers affects the LEDs
  set_busy_led(false); set_dirty_led(true);

  path.part = current_part;
  path.dir  = partition[path.part].current_dir;
  uart_trace(&path.dir, 0, sizeof(dir_t));
  uart_putcrlf();
  uart_flush();
  if (opendir(&buf->pvt.dir.dh, &path)) return;

  for (;;) {
    if (next_match(&buf->pvt.dir.dh,
                    buf->pvt.dir.matchstr,
                    buf->pvt.dir.match_start,
                    buf->pvt.dir.match_end,
                    buf->pvt.dir.filetype,
                    &dent) == 0)
    {
      uint8_t e_flags = 0;
      if (dent.opstype == OPSTYPE_FAT) {
        fat_filesystem = true;
        if (check_imageext(dent.pvt.fat.realname) != IMG_UNKNOWN)
          e_flags |= E_IMAGE;
      }
      // Current block full?
      if (entry_num == ENTRIES_PER_BLOCK) {
        entry_num = 0;
        buffer_t *old_buf = buf_cur;
        if ((buf_cur = alloc_system_buffer()) == NULL) {
          printf("alloc buf_cur failed, %d entries", entries);
          goto cleanup;
        }
        set_busy_led(false); set_dirty_led(true);
        buf_cur->pvt.buffer.next = NULL;
        old_buf->pvt.buffer.next = buf_cur;
      }

      // Store entry
      ep[entries] = (entry_t *) (buf_cur->data + entry_num * sizeof(entry_t));
      ustrncpy(ep[entries]->filename, dent.name, 16);
      ep[entries]->filesize = dent.blocksize;
      if ((dent.typeflags & EXT_TYPE_MASK) == TYPE_DIR)
        e_flags |= E_DIR;
      ep[entries]->flags = e_flags;
      entries++;
      entry_num++;
    } else {
      // No more directory entries to read
      break;
    }
  }
  printf("%d entries\r\n", entries);

  if (fat_filesystem)
    qsort(ep, entries, sizeof(entry_t*), compare);

  for (uint16_t i = 0; i < entries; i++) {
    printf("%3u: ", i);
    if (ep[i]->flags & E_DIR)
      uart_puts_P(PSTR(" DIR "));
    else if (ep[i]->flags & E_IMAGE)
      uart_puts_P(PSTR(" IMG "));
    else
      printf("%4u ", ep[i]->filesize);
    uint8_t filename[16 + 1];
    ustrncpy(filename, ep[i]->filename, 16);
    filename[16] = '\0';
    pet2asc(filename);
    printf("%s\r\n", filename);
    uart_flush();
  }
  uart_putcrlf();

#define DIRNAV_OFFSET   2
#define NAV_ABORT       0
#define NAV_PARENT      1

  mp = stack_mp[pos_stack];
  my = stack_my[pos_stack];
  printf("mp set to %d\r\n", mp);
  if (mp < (LCD_LINES - 1))
    my = mp;
  else
    my = 0;
  action = false;

  for (i=0; i < MAX_LASTPOS; i++) {
    if (pos_stack == i) uart_putc('>');
    printf("%d ", stack_mp[i]);
  }
  uart_putcrlf();

  for (;;) {
    lcd_clear();
    for (i = 0; i < LCD_LINES; i++) {
      lcd_locate(0, i);
      int8_t y = mp - my + i;
      if (y < 0) return; // should not happen!
      if (y < DIRNAV_OFFSET) {
        rom_menu_browse(y);
      } else {
        y -= DIRNAV_OFFSET;
        if (y >= entries) {
          lcd_puts_P(PSTR("-- End of dir --"));
          break;
        } else {
          lcd_print_dir_entry(y);
        }
      }
    }

    lcd_cursor(true);
    for (;;) {
      lcd_locate(0, my);
      //printf("mp: %u   my: %u\r\n", mp, my);
      //while (!get_key_state(KEY_ANY));
      if (get_key_autorepeat(KEY_PREV)) {
        if (mp > 0) {
          --mp;
          if (my > 0) --my;
          else {
            my = LCD_LINES - 1;
            if (mp < LCD_LINES) {
              while ((mp - my) >= DIRNAV_OFFSET) {
                --my;
                // TODO: is this really necessary?
                uart_puts_P(PSTR("my fixed\r\n"));
              }
            }
            break;
          }
        } else {
          my = LCD_LINES - 2;
          mp = entries + DIRNAV_OFFSET - 1;
          break;
        }
      }
      if (get_key_autorepeat(KEY_NEXT)) {
        if (mp < (entries -1 + DIRNAV_OFFSET)) {
          ++mp;
          if (my < (LCD_LINES - 1))  ++my;
          else {
            my = 0;
            break;
          }
        } else {
          mp = 0;
          my = 0;
          break;
        }
      }
      if (get_key_press(KEY_SEL)) {
        action = true;
        break;
      }
    }
    lcd_cursor(false);
    if (!action) continue;
    if (mp == NAV_ABORT) goto cleanup;
    if (mp == NAV_PARENT) {
      uart_puts_P(PSTR("CD_\r\n"));
      ustrcpy_P(command_buffer, PSTR("CD_"));
      command_length = 3;
      parse_doscommand();
      clear_command_buffer();
      stack_mp[pos_stack] = 0;
      stack_my[pos_stack] = 0;
      if (pos_stack > 0) --pos_stack;
      printf("pos_stack set to %d\r\n", pos_stack);
      if (current_error != ERROR_OK) goto cleanup;
      goto reread;
    }
    if (ep[mp - DIRNAV_OFFSET]->flags & E_DIR ||
        ep[mp - DIRNAV_OFFSET]->flags & E_IMAGE)
    {
      clear_command_buffer();
      ustrcpy_P(command_buffer, PSTR("CD:"));
      ustrncpy(command_buffer + 3, ep[mp - DIRNAV_OFFSET]->filename, 16);
      command_length = ustrlen(command_buffer);
      parse_doscommand();
      clear_command_buffer();
      if (current_error != ERROR_OK) goto cleanup;
      if (pos_stack < MAX_LASTPOS) {
        stack_mp[pos_stack]   = mp;
        stack_my[pos_stack++] = my;
        printf("pos_stack set to %d\r\n", pos_stack);
      }
      goto reread;
    }
  }

reread:
  free_buffer(buf);

  buffer_t *p = buf_tbl;
  do {
    p->allocated = 0;
    p = p->pvt.buffer.next;
  } while (p != NULL);

  p = first_buf;
  if (p != NULL) do {
    p->allocated = 0;
    p = p->pvt.buffer.next;
  } while (p != NULL);

  set_busy_led(false); set_dirty_led(true);
  active_buffers = save_active_buffers;
  if (mp == NAV_ABORT) return;
  goto start;

cleanup:
  mp = NAV_ABORT;
  goto reread;
}
示例#5
0
/**
 * create_changelist - create a swap list in a directory
 * @path    : path where the swap list should be created
 * @filename: name of the swap list file
 *
 * This function creates a swap list in @path by scanning that
 * directory and writing the names of all disk images it finds
 * into @filename. Returns nonzero if at least one image was found.
 */
static uint8_t create_changelist(path_t *path, uint8_t *filename) {
  FRESULT res;
  FILINFO finfo;
  DIR dh;
  FIL fh;
  UINT byteswritten;
  uint8_t *name;
  uint8_t found = 0;

  /* open directory */
  res = l_opendir(&partition[path->part].fatfs, path->dir.fat, &dh);
  if (res != FR_OK)
    return 0;

  /* open file */
  res = f_open(&partition[path->part].fatfs, &fh, filename, FA_WRITE | FA_CREATE_ALWAYS);
  if (res != FR_OK)
    return 0;

  /* scan directory */
  set_busy_led(1);
  finfo.lfn = ops_scratch;

  while (1) {
    res = f_readdir(&dh, &finfo);
    if (res != FR_OK)
      break;

    if (finfo.fname[0] == 0)
      break;

    if (!(finfo.fattrib & AM_DIR)) {
      if (check_imageext(finfo.fname) == IMG_IS_DISK) {
        /* write the name of disk image to file */
        found = 1;

        if (ops_scratch[0] != 0)
          name = ops_scratch;
        else
          name = finfo.fname;

        res = f_write(&fh, name, ustrlen(name), &byteswritten);
        if (res != FR_OK || byteswritten == 0)
          break;

        /* add line terminator */
        finfo.fname[0] = 0x0d;
        finfo.fname[1] = 0x0a;
        res = f_write(&fh, finfo.fname, 2, &byteswritten);
        if (res != FR_OK || byteswritten == 0)
          break;
      }
    }
  }

  f_close(&fh);

  set_busy_led(0);

  return found;
}